V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lianghui
V2EX  ›  程序员

请教最近 60 秒用户在线人数存储方案

  •  
  •   lianghui ·
    whiteclover · 2015-11-14 13:38:22 +08:00 · 3732 次点击
    这是一个创建于 3093 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近一个要求实时的用户人数在线曲线,展示最近 60 秒每一秒在线用户人数,维度大概是全国 400 个市级城市。

    因为使用了多机写入数据 redis ,如果分城市优先队列现在我们产品有近 100 个,也就是需要 100*400=4w 个 redis list , 如果将产品所有城市合并成一条记录只需要 400 个 list 。

    但问题是我们是分布式多机写入,不能保证多台服务同时写入数据是时序 push 进入 redis queue 。

    如果使用 key 过期机制,做 key/value 存储,又会因为 web 服务的时间矫正很难保证到秒级别,而可能在展示出最近 60 秒数据后,每秒请求实时一秒数据时因为系统服务的时间而可能无法找到数据。

    不知道大家又没什么遇到过此类问题。多多指教。

    17 条回复    2015-11-15 02:33:42 +08:00
    vietor
        1
    vietor  
       2015-11-14 13:48:11 +08:00 via Android
    没有绝对精确的,延时 60 秒也没什么。所有这些数据都是以曲线形式展示,所以追求所谓的精确没人 care
    msg7086
        2
    msg7086  
       2015-11-14 13:56:11 +08:00
    单独开一台机器做统计,其他的都甩锅给这台来做。
    canesten
        3
    canesten  
       2015-11-14 14:04:53 +08:00
    量有多大?只有 60 秒这一个需求吗? 60 秒外的数据都可以不要吗?
    likexian
        4
    likexian  
       2015-11-14 14:08:45 +08:00
    关键看你实际的在线人数有多少以及在全国各地的分布情况,适量的误差是必然的。
    ericls
        5
    ericls  
       2015-11-14 14:12:46 +08:00
    time series 可以用 influxdb 看看
    lianghui
        6
    lianghui  
    OP
       2015-11-14 14:25:28 +08:00
    @vietor 我们现在能做到延迟 5 秒左右的数据,但是总是要展示最近 60 秒的数据的
    @msg7086 是个好办法,问题现在架构可能改成这个代价有点高。
    @canesten 是的,只要看最近 60 秒, 每分钟的统计我们直接放数据库了。

    @ericls 感谢
    canesten
        7
    canesten  
       2015-11-14 14:31:36 +08:00
    量不大的话就单独一个 redis
    key=用户 id
    60 秒过期
    每次请求过来 keys *一下
    量不大的话 keys 也可以用用的
    简单实用
    noman
        8
    noman  
       2015-11-14 14:31:41 +08:00
    用 zset ,不用用 list ,分数是时间戳
    noman
        9
    noman  
       2015-11-14 14:33:32 +08:00
    用 zset ,不用用 list ,分数是时间戳
    出于性能考虑可以写一个 redis lua 小函数,复制删除并插入
    noman
        10
    noman  
       2015-11-14 14:33:56 +08:00
    复制-》负责,笔误
    beneo
        11
    beneo  
       2015-11-14 15:45:27 +08:00
    为啥不弄台机器,搞一个 table ,用户 id 映射到 table index 上面

    上线,异步消息, table[index] = 1, 下线,异步消息, table[index] = 0

    60 秒做一次 table 计数
    beneo
        12
    beneo  
       2015-11-14 15:46:36 +08:00
    此外,就算弄个假的,或者延时的,也是可以的嘛。

    看上去是那个样子,差不多数据就好了

    逃~
    msg7086
        13
    msg7086  
       2015-11-14 15:49:41 +08:00
    @lianghui 只是在请求的时候往某一特定服务器发个消息而已啊,应该不算太过分吧。
    如果服务器很多的话,服务器上放一个服务指向单一 redis 服务器然后序列化发 query 也是个办法。
    直觉上应该不会太麻烦吧……?

    再过激一些的, nginx 上插一个 lua 往 redis 里直接写 http 请求数据,然后开个脚本 loop 读了发也行。
    都不算太过侵入的。
    airyland
        14
    airyland  
       2015-11-14 15:57:32 +08:00   ❤️ 1
    @ericls influxdb 0.9 以上都是坑,现在的版本连 backup 都操作不了
    lianghui
        15
    lianghui  
    OP
       2015-11-14 16:21:12 +08:00
    @noman 用 zset 藐视不错,可以解决多机写的问题。
    @msg7086 确实可以,仔细看了现有的架构确实可以聚集到单机再写入,以便前端展示。
    @beneo 我们是以日志时间精确秒做 bucket 块一次性做并发更新用户状态,最后得到是一个产品全国个城市每秒在线人数计数。 可以延迟几秒出,但作为商用系统,是不能造假的。
    iwannaflytomoon
        16
    iwannaflytomoon  
       2015-11-15 01:42:53 +08:00
    就算你统计精确到秒级,你数据库统计的准了,客户网络也会有延迟啊,用浏览器打开你们后台页面看数据也会有延迟啊,要说差 5 秒都不能接受我很想知道你们的客户准备拿你们这个系统来做什么?
    msg7086
        17
    msg7086  
       2015-11-15 02:33:42 +08:00
    @iwannaflytomoon 国内数据延迟不过 0.1 秒
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2318 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 03:12 · PVG 11:12 · LAX 20:12 · JFK 23:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.