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

关于点赞模块在高并发下的优化处理,求方案

  •  
  •   totoro52 · 2020-08-11 14:57:26 +08:00 · 8398 次点击
    这是一个创建于 1542 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前我涉及到做点赞这块,起初的设计是直接落库,用户的点赞和取消点赞直接对记录进行加减,这样的方案似乎很简单看起来也没啥问题,但是一旦流量多了起来,数据库肯定扛不住这么频繁的读写。

    我参考了一些网上教程,基本都是采用 redis 异步入库,就是点赞和取消都交给 redis,redis 记录了点赞人和被点赞人,同时在另外记录点赞总数,然后通过定时任务进行异步落库并删除 redis 中的指定数据。

    但是现在新的问题来了,当我要查询某个文章的点赞总数的时候,怎么保证数据的一致性呢,岂不是查询的总数的时候需要 mysql+redis = 总数才能保证唯一性,因为 redis 入库后记录就被删除了,防止内存庞大,而且 redis 并不会做持久化,麻烦做过这方面的大牛给我指点指点

    29 条回复    2020-08-13 09:50:26 +08:00
    IMCA1024
        1
    IMCA1024  
       2020-08-11 15:02:14 +08:00
    非要实时的点赞数据吗,有特殊需求?
    totoro52
        2
    totoro52  
    OP
       2020-08-11 15:03:58 +08:00
    有的,点赞在前台展示是需要保证实时的
    fdingiit
        3
    fdingiit  
       2020-08-11 15:05:16 +08:00
    为什么要删 redis 数据?
    Veneris
        4
    Veneris  
       2020-08-11 15:06:10 +08:00   ❤️ 2
    totoro52
        5
    totoro52  
    OP
       2020-08-11 15:06:12 +08:00
    @IMCA1024 我的考虑是不实时,然后异步入库的定时时间设置短点,比如 5 分钟,但是这样的解决方案不满足需求。
    palmers
        6
    palmers  
       2020-08-11 15:07:31 +08:00
    是不是可以通过期策略 来解决部分问题?
    totoro52
        7
    totoro52  
    OP
       2020-08-11 15:07:38 +08:00
    @fdingiit 防止内存庞大
    luckyrayyy
        8
    luckyrayyy  
       2020-08-11 15:15:14 +08:00   ❤️ 1
    超大并发下查询准确实时的点赞数量,本身不就是个伪需求嘛...谁会关心这个?
    yuzo555
        9
    yuzo555  
       2020-08-11 15:20:06 +08:00   ❤️ 1
    Redis 设置过期时间,根据周期使用不同的 Redis 键名,比如周期一天,文章 ID 是 123,那么点赞键名比如说是 like_123_20200811 (计数),like_123_20200811_user ( list,记录用户)。

    第一次创建时(用 incr 增加计数键,判断返回值即可知道是否为第一次)设置一个 25 小时的过期时间。

    定时比如每天 0:30 统计昨天的数量,加到数据库。
    yuzo555
        10
    yuzo555  
       2020-08-11 15:21:26 +08:00
    如果更短的周期可以用时间戳除以周期秒数取整来代替日期
    ericgui
        11
    ericgui  
       2020-08-11 15:22:54 +08:00
    @luckyrayyy 其实这些都可以解决的,但就看你花费多大的成本。

    比如,超大并发下查询交易金额(双十一),这绝地的刚需,必须保证数据准确,对吧
    但超大并发下查询点赞数,就有点那啥了,确实没必要。
    rushssss
        12
    rushssss  
       2020-08-11 15:22:56 +08:00
    入库后删 redis 数据是个啥操作
    liyunlong41
        13
    liyunlong41  
       2020-08-11 15:26:43 +08:00 via iPhone
    Redis 使用 hash,大 key 使用文章 ID,小 key 为 userid,定时任务隔一段时间落库,没做过点赞,不知道这样是否能满足需求?
    limboMu
        14
    limboMu  
       2020-08-11 15:28:13 +08:00
    mysql 里记录的数也可以放到 redis 啊,只要加一个版本号,按版本更新 redis 和 mysql 里的值就好了呀
    rogwan
        15
    rogwan  
       2020-08-11 15:33:39 +08:00   ❤️ 1
    实时入库并没有什么大的压力,主要是查询。每次请求都要查询很多个点赞数的统计,这个有点过渡消耗了。一个取巧的方式是超过一定数量之后,就不再计算了,之间显示 “999” 这样。如果点赞数是一个重要的指标,那还是 redis 实时处理,批量入库。
    lithbitren
        16
    lithbitren  
       2020-08-11 15:36:25 +08:00
    点赞的精确需求一般都是前端解决,来回点赞取消前端先切数量,其他人的赞可以延迟处理
    sujin190
        17
    sujin190  
       2020-08-11 16:41:17 +08:00   ❤️ 1
    多高的并发啊,就算 mysql update +1 这个性能是非常高的吧,再加上分库分表啥的,十万级 tps 应该是能轻松达到的吧,而点赞的日志会受限写入性能,那么完全可以异步队列落地就是了

    先把点赞数加上去,前端缓存结果,然后用队列异步落地点赞记录,绰绰有余了

    再不行把点赞数加在 redis 里,点赞记录也在 redis 加缓存,然后点赞记录推队列,异步落地 mysql 一小短时间后再回写 redis 确保准确,这样还不够你用的话,估计预算该上亿了吧,还问啥啊,找点牛人再做一个专门为点赞优化的的数据库就是了,千万级 tps 都小 case 了
    CoderGeek
        18
    CoderGeek  
       2020-08-11 17:06:19 +08:00
    redis 自增为啥不行呢
    janxin
        19
    janxin  
       2020-08-11 17:39:08 +08:00
    感觉是个伪需求,要看你们的数据量大概是什么样子的。

    其实你提到的加和处理就是一个方案,而且基本也能满足绝大部分场景下的需求。

    更进一步方案需要根据你的数据量评估啊,比如你并发很高但是热点很集中和并发很高热点数据不是相对集中做法都是不一样的...
    wysnylc
        20
    wysnylc  
       2020-08-11 17:43:30 +08:00
    要性能就得接受延时,要实时就得接受低速,二者不可皆得
    microget
        21
    microget  
       2020-08-11 17:43:53 +08:00
    产品经理的 KPI 吧
    swulling
        22
    swulling  
       2020-08-11 17:46:06 +08:00 via iPhone
    其实以你们产品的并发,根本就用不上 redis
    wweir
        23
    wweir  
       2020-08-11 17:56:08 +08:00 via Android
    既要实时又要高并发,单点可以实现,不过说起来很多业务不敢这么玩
    totoro52
        24
    totoro52  
    OP
       2020-08-11 18:20:41 +08:00
    哈哈哈 谢谢各位的回复,我懂了,我明天 TM 就把产品经理杀了祭天
    locoz
        25
    locoz  
       2020-08-11 18:21:00 +08:00 via Android
    消息队列慢慢入库+伪实时数量?
    1018ji
        26
    1018ji  
       2020-08-11 18:21:20 +08:00
    实时点赞,这真是个牛逼的需求
    Leigg
        27
    Leigg  
       2020-08-11 18:26:16 +08:00 via Android
    实时点赞真没必要,非要解决的话上数据放内存里。
    kisshere
        28
    kisshere  
       2020-08-11 22:30:25 +08:00 via Android
    都能把 MySQL 的 update+1 给写崩溃了,你这站的访问量也太大了吧,如果真有那么大,别拿 MySQL 存点赞数,拿其他硬盘型的 nosql 存
    CoderGeek
        29
    CoderGeek  
       2020-08-13 09:50:26 +08:00
    减少数据库更新 第一次从库加载在到 redis 做自增 一段时间 定期刷库 不好吗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1106 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 22:52 · PVG 06:52 · LAX 15:52 · JFK 18:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.