系统 session
设置为 2 小时, 并且我的 session
信息是直接存储在 redis
里面的
现在利用 redis
的 zset
统计人数,每当用户登陆的时候, zadd
添加当前用户 id,score 为登陆时间戳
这个比较适合统计 一天 或者 一周 的上线人数, 直接 zrange
结果也比较准确
如果我想同时利用 zset
统计 当前在线人数, 必须得 每当用户访问页面时, 更新用户的 score 为新的时间戳, 是这样吗?
那么我直接在 redis
中维护一个 cur_online_user_num
的 key
, 每当 session
创建的时候, 值++ , 每当 session
失效的时候 值-- , 这样是不是更好点, 避免了 频繁更新 score
的问题?
1
joaner 2018-06-22 17:09:15 +08:00 1
是的,需要每次访问页面都用 ZADD 更新时间,redis 会按用户 ID 自动去重。
查询 2 小时内的在线人数时:`ZCOUNT views ($now_timestamp-7200) 9999999999` 你后面的方案简单点,但 session 失效时的钩子不好设置。 |
2
hiboshi 2018-06-22 17:38:53 +08:00
如果用户很长时间不刷新呢?不也在线 比如看一篇比较难懂的文章,建议加个心跳接口。每间隔一段时间 t 去做刷新 last_time.
|
3
zzf2017 2018-06-22 17:42:18 +08:00
大佬有文章或者方法吗?我最近也在弄这些东西,但是处理起来不太好
|
4
holyghost 2018-06-22 18:02:25 +08:00 1
|
6
a7a2 2018-06-22 18:10:07 +08:00
避免频繁更新 redis 不是这样设计
而是“每当用户访问页面时”记录在代码 map 中,开一个专门处理这个 map 数据的任务,每 1 分钟处理一次,把 map 记录的页面访问时间对比 redis 时间才更新。 就是 redis 前自己缓存一下的意思,网站 pv 量很高的时候也不至于把 redis 搞得太忙 @sakudie |
7
sakudie OP @hiboshi 这个 session 在服务端有定时检测的,过期的会被主动清理掉,session 有效时间设置为 2 小时够长了。
|
9
owenliang 2018-06-22 18:25:30 +08:00 1
分享一个我的实现。
假设 2 分钟以内访问过网站,算作在线。 那么,当一个访问请求过来的时候,假设此时是 1970 年以来的第 N 分钟,那么你应该执行这样一个 Redis 命令: pipeline zrem online_${N-1} uid zadd online_${N} 0 uid expire online_${N} 1800 exec 那么你想知道在线用户数量,只需要 zcard online_${N-1} + zcard online_${N},就是 2 分钟内的用户总数量了。 考虑实际工程问题,用户量大的情况下肯定不能都写一个 redis 集合,可以按 uid 取模到不同的 Redis 实例中,最后统计时做加和。 |
10
a7a2 2018-06-22 18:31:32 +08:00 1
@sakudie 不需要比较了 直接 map 里面有最后的浏览记录直接写 redis 写完要清空 map 即可免于比较。遍历 map 是必须的,速度也肯定很快,redis 操作这里使用 hmset 效率比单个 set 要高(猜测)
|
11
a7a2 2018-06-22 18:45:51 +08:00
@sakudie
记得 遍历+清空 map 前要加锁,写最后浏览数据到 map 建议通过 mq 完成,遍历 map 数据写 redis 也 mq。 这样保障单服务器每秒 pv 上万的时候不至于在 每当遍历 map 时候卡住一下,因为遍历+清空 map 前有一个锁 这样才能保证每一个数据不丢失 |
12
julyclyde 2018-06-23 11:57:34 +08:00
zrange 速度很慢的
|