最近一个要求实时的用户人数在线曲线,展示最近 60 秒每一秒在线用户人数,维度大概是全国 400 个市级城市。
因为使用了多机写入数据 redis ,如果分城市优先队列现在我们产品有近 100 个,也就是需要 100*400=4w 个 redis list , 如果将产品所有城市合并成一条记录只需要 400 个 list 。
但问题是我们是分布式多机写入,不能保证多台服务同时写入数据是时序 push 进入 redis queue 。
如果使用 key 过期机制,做 key/value 存储,又会因为 web 服务的时间矫正很难保证到秒级别,而可能在展示出最近 60 秒数据后,每秒请求实时一秒数据时因为系统服务的时间而可能无法找到数据。
不知道大家又没什么遇到过此类问题。多多指教。
1
vietor 2015-11-14 13:48:11 +08:00 via Android
没有绝对精确的,延时 60 秒也没什么。所有这些数据都是以曲线形式展示,所以追求所谓的精确没人 care
|
2
msg7086 2015-11-14 13:56:11 +08:00
单独开一台机器做统计,其他的都甩锅给这台来做。
|
3
canesten 2015-11-14 14:04:53 +08:00
量有多大?只有 60 秒这一个需求吗? 60 秒外的数据都可以不要吗?
|
4
likexian 2015-11-14 14:08:45 +08:00
关键看你实际的在线人数有多少以及在全国各地的分布情况,适量的误差是必然的。
|
5
ericls 2015-11-14 14:12:46 +08:00
time series 可以用 influxdb 看看
|
6
lianghui OP |
7
canesten 2015-11-14 14:31:36 +08:00
量不大的话就单独一个 redis
key=用户 id 60 秒过期 每次请求过来 keys *一下 量不大的话 keys 也可以用用的 简单实用 |
8
noman 2015-11-14 14:31:41 +08:00
用 zset ,不用用 list ,分数是时间戳
|
9
noman 2015-11-14 14:33:32 +08:00
用 zset ,不用用 list ,分数是时间戳
出于性能考虑可以写一个 redis lua 小函数,复制删除并插入 |
10
noman 2015-11-14 14:33:56 +08:00
复制-》负责,笔误
|
11
beneo 2015-11-14 15:45:27 +08:00
为啥不弄台机器,搞一个 table ,用户 id 映射到 table index 上面
上线,异步消息, table[index] = 1, 下线,异步消息, table[index] = 0 60 秒做一次 table 计数 |
12
beneo 2015-11-14 15:46:36 +08:00
此外,就算弄个假的,或者延时的,也是可以的嘛。
看上去是那个样子,差不多数据就好了 逃~ |
13
msg7086 2015-11-14 15:49:41 +08:00
@lianghui 只是在请求的时候往某一特定服务器发个消息而已啊,应该不算太过分吧。
如果服务器很多的话,服务器上放一个服务指向单一 redis 服务器然后序列化发 query 也是个办法。 直觉上应该不会太麻烦吧……? 再过激一些的, nginx 上插一个 lua 往 redis 里直接写 http 请求数据,然后开个脚本 loop 读了发也行。 都不算太过侵入的。 |
15
lianghui OP |
16
iwannaflytomoon 2015-11-15 01:42:53 +08:00
就算你统计精确到秒级,你数据库统计的准了,客户网络也会有延迟啊,用浏览器打开你们后台页面看数据也会有延迟啊,要说差 5 秒都不能接受我很想知道你们的客户准备拿你们这个系统来做什么?
|
17
msg7086 2015-11-15 02:33:42 +08:00
@iwannaflytomoon 国内数据延迟不过 0.1 秒
|