redis 统计在线人数的疑问

2018-06-22 16:04:33 +08:00
 sakudie

系统 session 设置为 2 小时, 并且我的 session 信息是直接存储在 redis 里面的

现在利用 rediszset 统计人数,每当用户登陆的时候, zadd 添加当前用户 id,score 为登陆时间戳

这个比较适合统计 一天 或者 一周 的上线人数, 直接 zrange 结果也比较准确

如果我想同时利用 zset 统计 当前在线人数, 必须得 每当用户访问页面时, 更新用户的 score 为新的时间戳, 是这样吗?

那么我直接在 redis 中维护一个 cur_online_user_numkey, 每当 session 创建的时候, 值++ , 每当 session 失效的时候 值-- , 这样是不是更好点, 避免了 频繁更新 score 的问题?

6480 次点击
所在节点    Redis
12 条回复
joaner
2018-06-22 17:09:15 +08:00
是的,需要每次访问页面都用 ZADD 更新时间,redis 会按用户 ID 自动去重。
查询 2 小时内的在线人数时:`ZCOUNT views ($now_timestamp-7200) 9999999999`

你后面的方案简单点,但 session 失效时的钩子不好设置。
hiboshi
2018-06-22 17:38:53 +08:00
如果用户很长时间不刷新呢?不也在线 比如看一篇比较难懂的文章,建议加个心跳接口。每间隔一段时间 t 去做刷新 last_time.
zzf2017
2018-06-22 17:42:18 +08:00
大佬有文章或者方法吗?我最近也在弄这些东西,但是处理起来不太好
holyghost
2018-06-22 18:02:25 +08:00
zzf2017
2018-06-22 18:07:51 +08:00
@holyghost 你的这种太高端了,还是全英文的,看不懂啊
a7a2
2018-06-22 18:10:07 +08:00
避免频繁更新 redis 不是这样设计

而是“每当用户访问页面时”记录在代码 map 中,开一个专门处理这个 map 数据的任务,每 1 分钟处理一次,把 map 记录的页面访问时间对比 redis 时间才更新。

就是 redis 前自己缓存一下的意思,网站 pv 量很高的时候也不至于把 redis 搞得太忙
@sakudie
sakudie
2018-06-22 18:20:40 +08:00
@hiboshi 这个 session 在服务端有定时检测的,过期的会被主动清理掉,session 有效时间设置为 2 小时够长了。
sakudie
2018-06-22 18:22:28 +08:00
@a7a2 如果放到 map 里面,到时候就算定期比较、更新不是要遍历 zset 吗
owenliang
2018-06-22 18:25:30 +08:00
分享一个我的实现。

假设 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 实例中,最后统计时做加和。
a7a2
2018-06-22 18:31:32 +08:00
@sakudie 不需要比较了 直接 map 里面有最后的浏览记录直接写 redis 写完要清空 map 即可免于比较。遍历 map 是必须的,速度也肯定很快,redis 操作这里使用 hmset 效率比单个 set 要高(猜测)
a7a2
2018-06-22 18:45:51 +08:00
@sakudie
记得 遍历+清空 map 前要加锁,写最后浏览数据到 map 建议通过 mq 完成,遍历 map 数据写 redis 也 mq。
这样保障单服务器每秒 pv 上万的时候不至于在 每当遍历 map 时候卡住一下,因为遍历+清空 map 前有一个锁 这样才能保证每一个数据不丢失
julyclyde
2018-06-23 11:57:34 +08:00
zrange 速度很慢的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/465067

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX