delphi 软件在线人数统计_Redis实现实时统计在线用户人数的几种方案

2023-11-20

一个业务系统网站每天人数的访问量是多少,在线人数是多少? 这种业务我们在开发中就要预留,也是在我们的设计范围内的咯!因为一个正在运营的网站,每天都会用到统计。

那在线人数是如何统计的呢,这里有几种方案,代码用laravel框架。可以作为开发中参考。

1 用表统计方式

用数据表统计在线人数,这种方式只能用在并发量不大的情况下。

首先我们先新建表:user_login

bb8b379767c497bad35118f25d677b87.png

user_login表

模拟用户登录,不存在用户就存入表,存在的则更新登录信息

// 客户端唯一的识别码$client_id = session()->getId(); //用户是否已存在$user = DB::table('user_login')    ->where('token', $client_id)    ->first(); //不存在则插入数据if (empty($user)) {    $data = [        'token' => $client_id,        'username' => 'user_' . $client_id, // 模拟用户        'uid' => mt_rand(10000000, 99999999),   //模拟用户id        'create_time' => date('Y-m-d H:i:s'),        'update_time' => date('Y-m-d H:i:s')    ];    DB::table('user_login')->insert($data);} else {        // 存在则更新用户登录信息    DB::table('user_login')     ->where('token', $client_id)     ->update([          'update_time' => date('Y-m-d H:i:s')      ]);}

这里还需要定期清理无任何操作的用户,假如用户一个小时内无任何操作,我们可以记为无效用户

代码如下:

// 客户端唯一的识别码$client_id = session()->getId(); //用户是否已存在$user = DB::table('user_login')    ->where('token', $client_id)    ->first(); //不存在则插入数据if (empty($user)) {    $data = [        'token' => $client_id,        'username' => 'user_' . $client_id, // 模拟用户        'uid' => mt_rand(10000000, 99999999),   //模拟用户id        'create_time' => date('Y-m-d H:i:s'),        'update_time' => date('Y-m-d H:i:s')    ];    DB::table('user_login')->insert($data);} else {        // 存在则更新用户登录信息    DB::table('user_login')     ->where('token', $client_id)     ->update([          'update_time' => date('Y-m-d H:i:s')      ]);}

我们可以实现的功能:

1)当前在线人数

2)某时间段内在线人数

3)最新上线的用户

4)指定用户是否在线

// 可实现功能一:当前总共在线人数$c = DB::table('user_login')->count();echo '当前在线人数:' . $c . '
'; // 可实现功能二:某时间段内在线人数$begin_date = '2020-08-13 09:00:00';$end_date = '2020-08-13 18:00:00';$c = DB::table('user_login') ->where('create_time', '>=', $begin_date) ->where('create_time', '<=', $end_date) ->count();echo $begin_date . '-' . $end_date . '在线人数:' . $c . '
'; // 可实现功能三:最新上线的用户$newest = DB::table('user_login') ->orderBy('create_time', 'DESC') ->limit(10) ->get();echo '最新上线的用户有:';foreach ($newest as $value) { echo $value->username . ' ';}echo '
'; // 可实现功能四:指定用户是否在线$username = 'user_1111';$online = DB::table('user_login') ->where('username', $username) ->exists();echo $username . ($online ? '在线' : '不在线');

2 使用redis有序集合实现在线人数统计

因为是内存中,所以效率很高,可以统计某个时间段内的在线人数,可以做各种聚合操作。但是如果在线人数比较多的情况下,会比较占用内存。还有一点:

无法通过用户操作时间清除掉无效用户,只有手动登出的用户才会从集合中删除。

代码如下:

// 客户端唯一的识别码$client_id = session()->getId();echo $client_id . '
'; // 按日期生成key$day = date('Ymd');$key = 'online:' . $day; // 是否在线$is_online = Redis::zScore($key, $client_id);if (empty($is_online)) { // 不在线,加入当前客户端 Redis::zAdd($key, time(), $client_id);} // 可实现功能一:当前总共在线人数$c = Redis::zCard($key);echo '当前在线人数:' . $c . '
'; // 可实现功能二:某时间段内在线人数$begin_date = '2020-08-13 09:00:00';$end_date = '2020-08-13 18:00:00';$c = Redis::zCount($key, strtotime($begin_date), strtotime($end_date));echo $begin_date . '-' . $end_date . '在线人数:' . $c . '
'; // 可实现功能三:最新上线的用户,时间从小到大排序$newest = Redis::zRangeByScore($key, '-inf', '+inf', ['limit' => [0, 50]]);echo '最新上线的用户有:';foreach ($newest as $value) { echo $value . ' ';}echo '
'; // 可实现功能四:指定用户是否在线$username = $client_id;$online = Redis::zScore($key, $client_id);;echo $username . ($online ? '在线' : '不在线') . '
'; // 可实现功能五:昨天和今天都上线的客户$yestoday = Carbon::yesterday()->toDateString();$yes_key = str_replace('-', '', $yestoday);$members = [];Redis::pipeline(function ($pipe) use ($key, $yes_key, &$members) { Redis::zinterstore('new_key', [$key, $yes_key], ['aggregate' => 'min']); $members = Redis::zRangeByScore('new_key', '-inf', '+inf', ['limit' => [0, 50]]); //dump($members);});echo '昨天和今天都上线的用户有:';foreach ($members as $value) { echo $value . ' ';}

3 使用hyperloglog做统计

跟有序集合方式不同,hyperloglog十分节约空间,但是实现的功能也非常单一,只能统计在线人数,不能实现其余的任何功能。

Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。

在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

// note HyperLogLog 只需要知道在线总人数for ($i=0; $i < 6; $i++) {    $online_user_num = mt_rand(10000000, 99999999);     //模拟在线人数    var_dump($online_user_num);    for ($j=1; $j < $online_user_num; $j++) {         $user_id = mt_rand(1, 100000000);        $redis->pfadd('002|online_users_day_'.$i, [$user_id]);    }}
$count = 0;for ($i=0; $i < 3; $i++) {     $count += $redis->pfcount('002|online_users_day_'.$i);    print_r($redis->pfcount('002|online_users_day_'.$i). "");}var_dump($count); //note  3 days total online numvar_dump($redis->pfmerge('002|online_users_day_both_3', ['002|online_users_day_0', '002|online_users_day_1', '002|online_users_day_2']));var_dump($redis->pfcount('002|online_users_day_both_3'));

这种方案仅仅只能统计出某个时间段在线人数的总量, 对在线用户的名单却无能为力,但是却挺节省内存的,对统计数据要求不多情况下 ,我们便可以考虑这种方案。

4 使用bitmap统计

bitmap就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间。

bitmap常用来做比如用户签到、活跃用户、在线用户等功能。

代码如下

// 模拟当前用户$uid = request('uid'); $key = 'online_bitmap_' . date('Ymd'); // 设置当前用户在线Redis::setBit($key, $uid, 1); // 可实现功能1:在线人数$c = Redis::bitCount($key);echo '在线人数:' . $c . '
'; // 可实现功能2:指定用户是否在线$online = Redis::getBit($key, $uid);echo $uid . ($online ? '在线' : '不在线') . '
'; // 可实现功能3:昨天和今天均上线的用户总数$yestoday = Carbon::yesterday()->toDateString();$yes_key = str_replace('-', '', $yestoday);$c = 0;Redis::pipeline(function ($pipe) use ($key, $yes_key, &$c) { Redis::bitOp('AND', 'yest', $key, $yes_key); $c = Redis::bitCount('yest');});echo '昨天和今天都上线的用户数量有:' . $c . '
'; // bitmap无法统计具体有哪些用户

bitmap消耗的内存空间不多, 统计的信息却挺多的,这种方案是值得推荐一下的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

delphi 软件在线人数统计_Redis实现实时统计在线用户人数的几种方案 的相关文章

  • 02-RabbitMQ之Docker安装Rabbit单机与集群

    一 docker安装单机rabbit 1 查找rabbitmq镜像或者在docker仓库查看rabbitmq镜像 docker search rabbitmq 2 拉取最新的rabbitmq docker pull rabbitmq 3 运
  • KEIL经常出现 Encountered an improper argument 弹窗

    关于 keil5 使用在线调试时 经常出现 Encountered an improper argument 弹窗 经实测 可有如下方法 方法1 下载UV4 exe 替换本机电脑 Keil UV4目录下的UV4 exe 更换后 如果不能编译
  • 7-14 解一元一次方程 (17 分)

    请编写程序 解一元一次方程 ax b 0 一元一次方程求解公式为 x ab 求解要求 a 0 方程有唯一解 输出解 a 0 b 0 方程无解 输出no solution a 0 b 0 则方程有无穷多解 输出Infinitely solut
  • The absolute uri: http://java.sun.com/jsp/jstl/fmt cannot be resolved in either web.xml or the jar

    错误提示 org apache jasper JasperException file H netbeans workspace netbeans 6 9 ShoppingSystemOnline build web system fron
  • [LDUoj 倍增] 题解

    星星之火 可以燎原 细节的地方慢慢补充 欢迎提出问题 私聊 留言均可 A 跳跳棋 较难 B 聚会 板子题 C 祖孙询问 板子题 D Dis 板子题 E 次小生成树 严格次小生成树 难 F 异象石 难度适中 G 暗的连锁 难度适中 H 点的距
  • 3D游戏编程实践——Priests and Devils

    编程实践 Priests and Devils github链接 https github com ctlchild SYSU unity3d learning tree master hw2 Priests and Devils is a
  • 给Protobuf中的repeated类型变量添加子项

    Protobuf为repeated类型变量生成的自动代码 不提供通常的类似add item item 的添加子项的成员函数 Protobuf的做法是 UserDocChangesResp changes DocChangeInfo chan
  • Linux shell 编程之 - 合并两个文件

    两个文件a1 b1 内容分别如下 a1 1 2 3 b1 a b c 如何把它们合在一起内容如下的 1 a 2 b 3 c paste d a1 a2 SUN的Solaris只能合并12个文件 sco5 5下ksh只能合并6个文件 在aix
  • Allegro PCB封装焊盘介绍(一)

    PCB封装焊盘结构 焊盘结构如图 1所示 图 1焊盘结构 锡膏层 SMT刷锡膏贴片用 一般贴片焊盘要选 跟焊盘等大 阻焊层 把焊盘裸露出来 不开的话 焊盘会被油墨盖住 这样无法焊接哦 一般比焊盘大0 1mm 顶层 底层焊盘 实际焊盘大小 电
  • tensorRT 与 torchserve-GPU性能对比

    实验对比 前端时间搭建了TensorRT Torchserve GPU 最近抽时间将这两种方案做一个简单的实验对比 实验数据 Cuda11 0 Xeon 6242 3 1 80 RTX3090 24G Resnet50 TensorRT T
  • nosql练习

    1 string类型数据的命令操作 1 设置键值 2 读取键值 3 数值类型自增1 4 数值类型自减1 5 查看值的长度 2 list类型数据的命令操作 1 对列表city插入元素 Shanghai Suzhou Hangzhou 2 将列
  • Qt中代码添加背景图

    第一步 选择一张背景图下到本地 第二步 在qt中点击添加新文件选择图中位置 随便起个名字 点击下一步 这时项目中多出一个目录 选择打开资源编辑器 底部添加前缀 注意该前缀是在内部使用图的路径 点击添加 gt 添加前缀 我这里直接使用的 作为
  • STM32F4实现SD卡读写

    更多交流欢迎关注作者抖音号 81849645041 目的 熟悉SD卡和SDIO工作原理 掌握SD卡的读写 原理 大多单片机系统都需要大容量存储设备 以存储数据 目前常用的有 U 盘 FLASH 芯片 SD 卡等 他们各有优点 综合比较 最适
  • 2020网易笔试编程题(一)

    题目 在一次聚会中 教授们被要求写下自己认可哪位教授的学术成果 也可以写自己 且可能出现重复 已知 如果教授A认可教授B 且教授B认可教授C 那么即可视为教授A也认可教授C 现在我们想知道多少对教授是两两互相认可的 输入举例 输入教授人数
  • oracle中replace怎么用,oraclereplace函数怎么用

    1 REPLACE函数怎么用 REPLACE 参数1 参数2 参数3 参数4 参数1 是要替换其部分字符的文本 参数2 是要用参数4替换的参数1中字符的起始位置 参数3 是希望REPLACE用参数4替换参数1中从参数2开始算起的字符个数 参
  • js 将一维数组转为二维数组并分组

    let arr a W b W01 a W b W02 a WC b WC01 a WC b WC02 a WC b WC02 a WC b WC02 let map arr forEach item gt if map item a ma
  • 理解Spring定时任务@Scheduled的两个属性fixedRate和fixedDelay

    fixedRate和fixedDelay都是表示任务执行的间隔时间 fixedRate和fixedDelay的区别 fixedDelay非常好理解 它的间隔时间是根据上次的任务结束的时候开始计时的 比如一个方法上设置了fixedDelay
  • js 手机、邮箱、身份证格式验证

  • 使用Transformer与无监督学习,OpenAI提出可迁移至多种NLP任务的通用模型

    OpenAI 最近通过一个与任务无关的可扩展系统在一系列语言任务中获得了当前最优的性能 目前他们已经发布了该系统 OpenAI 表示他们的方法主要结合了两个已存的研究 即 Transformer 和无监督预训练 实验结果提供了非常令人信服的

随机推荐

  • 不相交集类(并查集)

    并查集 就是只有合并和 查找操作的一种数据结构 很简单 主要判断一个元素是否在一个集合里 主要应用在最小生成树 Kruskal算法 看到图的时候会将实现代码贴上 package chapter8 类名 DisjSets 说明 实现并查集 按
  • Siddhi

    1 Siddhi是什么 Siddhi是一个开源的流处理和复杂事件处理引擎 由WSO2公司开发 它提供了一个强大而灵活的框架 用于处理实时流数据和复杂事件 官网 2 Siddhi特点和功能 Siddhi具有以下特点和功能 1 实时流处理 Si
  • TypeScript之元组、数组以及 as const

    一 元组 数组 在 TS 中 元组表示 这个数组有不同的类型 简单的一句话来表述 如果类型相同的一组数据就是数组 反之就是元组 数组的 api 对于元组来讲也是通用的 push pop等 只是类型不同 1 数组的定义 定义数组的方式 let
  • 个人喜欢的网站http://www.w3school.com.cn

    http www w3school com cn 这个网站很好 能帮助很多人
  • 用 JAVA 编写一个 M3U8 视频下载器

    总览 本文简要介绍了 M3U8 视频文件格式 并且用代码实现下载一个 M3U8 文件的视频资源 背景 前段时间在做视频真实地址解析下载时候发现很多视频网站用了 CKplayer 播放的时候传过来的参数是一个 M3U8 文件的链接 和普通的视
  • 【JS基础数组方法】数组过滤、切割、查询

    1 Array filter 数组过滤 语法 array filter function currentValue index arr thisValue 有两个参数 一个是函数 为必选参数 函数中又有三个参数 currentValue为当
  • Unity单元测试流程

    文章目录 环境 流程 1 创建一个存放 单元测试程序集 的目录 2 打开 Test Runner 窗口 3 选择单元测试模式 4 创建单元测试程序集 5 创建测试脚本 6 运行测试 环境 Unity 2020 3 3f1 流程 1 创建一个
  • centos 通过docker搭建 kurento-media-server 遇到的各种奇葩的大坑

    kurento media server里的坑有n多 而且很多是极其初级的坑 忍不住吐槽一下 不知道是故意的还是他们的程序员刚毕业 1 首先kurento media server只能安装在ubuntu14 和16版本 2 如果你想在cen
  • ST-GCN的学习之路(一)论文分析

    目录 St GCN 2018AAAI Introduction Multiple modalities of human action The weakless of previous methods This work s advanta
  • antv-g2语法总结

    目的 使用antv g2完成一个图表 该图表有两种结构组成 散点图与矩形图组成 我们需要将散点图与矩形图分别在两个view中绘制 所以还需要总结一下view的概念 第一步语法基础 首先是引入相应依赖 其次是创建html容器 div div
  • vue---element el-tree全选、清空、展开、收缩等基本功能总结

    目录 el tree 1 获取选中 2 设置选中 3 全选 清空 4 展开收缩 5 完整代码 el tree 用来展示树型结构的信息 具备展开和折叠的功能 通过案例介绍相关知识点内容 案例实现的功能如下 1 获取选中 可通过node和key
  • 内网渗透工具-反向代理nps使用分析

    0x1 简介 nps 是一款轻量级 高性能 功能强大的内网穿透代理服务器 支持 tcp udp 流量转发 可在网页上配置和管理各个tcp udp隧道 内网站点代理 http https解析等 功能强大 操作方便 0x2 前期准备 1 安装编
  • python运算符

    usr bin python encoding utf 8 print fish 输出方式一 print Hello World 输出方式二 if True 判断语法 print True else print False str Runo
  • OSI七层模型详解

    OSI 七层模型通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯 因此其最主要的功能就是帮助不同类型的主机实现数据传输 完成中继功能的节点通常称为中继系统 在OSI七层模型中 处于不同层的中继系统具有不同的名称 一个设备工作
  • Tomcat的多实例和动静分离

    目录 一 多实例 二 nginx tomcat的负载均衡和动静分离 三 Tomcat 客户端 gt 四层代理 gt 七层代理 gt tomcat服务器 实验 问题总结 tomcat日志文件 usr local tomcat logs cat
  • Python机器学习从零开始(五)算法审查

    目录 1 审查分类算法 1 1线性算法审查 1 2非线性算法审查 2 审查回归算法 2 1线性算法审查 2 2非线性算法审查 3 算法比较 总结 程序测试是展现BUG存在的有效方式 但令人绝望的是它不足以展现其缺位 艾兹格 迪杰斯特拉 Ed
  • 2022322

    没有人天生就会某一项技能 只有在后天的成长中 不断的练习和重复 才会越来越熟练 爆发吧 小宇宙 基础知识 1 html css 2 js vue的使用 1 vue的原理和高级用法 1 html css 3 vue cli4中的webpack
  • Function overloaded in C++

    重载定义 如果两个函数名字相同并且在相同的域中被声明 但是参数表不同 则它们就是重载函数 重载函数条件 2 1 参数类型或参数个数不同 2 2 返回值不同不能视为重载 2 3 是否为常函数不能视为重载 2 4 对于普通类型参数只有const
  • C# 委托详解

    文章目录 前言 一 委托是什么 1 官方关于委托的概述 2 通俗解释 二 如何使用委托 1 使用委托详解 1 申明委托 2 编写委托对应的方法 3 实例化委托 4 使用委托 5 委托使用的综合案例 2 使用多播委托详解 委托链 1 关于多播
  • delphi 软件在线人数统计_Redis实现实时统计在线用户人数的几种方案

    一个业务系统网站每天人数的访问量是多少 在线人数是多少 这种业务我们在开发中就要预留 也是在我们的设计范围内的咯 因为一个正在运营的网站 每天都会用到统计 那在线人数是如何统计的呢 这里有几种方案 代码用laravel框架 可以作为开发中参