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

求教各位彦祖,点赞系统设计的最佳实践?

  •  
  •   GreatEscape · 2021-07-27 10:57:48 +08:00 · 3727 次点击
    这是一个创建于 1202 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我们有一个类知乎的服务,日活 500 万左右;用户可以对文章进行点赞,但是用户只有在文章详情页才可以进行点赞相关的查询和操作,QPS 也不高,所以直接走数据库查询也没有太大性能问题。 最近产品提出将点赞按钮前置到文章列表中的需求,我们每次分页会查询 50 篇文章的信息,肯定不能直接走数据库了。 目前我初步想法是将用户点赞数据放到 Redis 位图中,考虑到用户点赞其实是个相对低频的操作,点赞、取消点赞都直接操作 Redis,异步刷新到 DB,这样牺牲了部分可靠性,比如 Redis 挂了导致用户操作没有同步到 DB 、或者 Redis 操作成功,但是 DB 操作失败如何处理,还要考虑如异步调用乱序如何处理。 所以想请教下各位 V2er,这类点赞系统的设计有没有一些最佳实践?比如走 ES 或 Mongo?

    19 条回复    2021-07-29 10:41:59 +08:00
    love2020
        1
    love2020  
       2021-07-27 11:06:09 +08:00
    25 次点击,没人回答你的问题。 [也许 Redis 真的没那么容易挂。。]
    securityCoding
        2
    securityCoding  
       2021-07-27 11:08:04 +08:00
    redis-》进程内缓存-》 DB,完全能扛得住
    GreatEscape
        3
    GreatEscape  
    OP
       2021-07-27 11:14:02 +08:00
    服了,发出来怎么换行等格式全没了。。。
    bnrwnjyw
        4
    bnrwnjyw  
       2021-07-27 11:22:30 +08:00
    @GreatEscape markdown 要换两行
    no1xsyzy
        5
    no1xsyzy  
       2021-07-27 11:34:13 +08:00
    我猜测将「文章被点赞总数」一并进行存储再添加[用户,文章]联合索引即可满足性能需求。
    最佳实践应是图数据库

    ps.
    markdown 换两行 = 分 <p>
    空两格换一行 = <br>
    hahasong
        6
    hahasong  
       2021-07-27 12:00:43 +08:00
    各家主流的做法是,点赞 /取消 界面 UI 实时反馈(与请求无关),然后上报一次事件。你可以把事件记在队列里。然后匀速消费,统计点赞数和记日志。你不记操作日志,点赞人进去怎么看到自己是点了还是没点


    也可以简化做,不用队列,直接请求接口,但是 WAF 做下限流就行,大不了太多了返回 “操作频繁,请稍后再试”
    xuanbg
        8
    xuanbg  
       2021-07-27 12:16:55 +08:00
    分页查询怎么就不能直接查表了? left join 点赞记录表就好了嘛
    tedcon
        9
    tedcon  
       2021-07-27 15:07:53 +08:00
    点赞的数量 也就是读操作可以放到缓存。写操作先入 db 然后同步到缓存。这不是常规操作吗?
    GreatEscape
        10
    GreatEscape  
    OP
       2021-07-27 16:17:56 +08:00
    @xuanbg 看 QPS 的,我们之前点赞列表直接联表查,有次做活动,直接引导用户跳转到自己的点赞列表,联表查就差点查挂了。
    bthulu
        11
    bthulu  
       2021-07-28 09:02:47 +08:00
    写入浏览器本地数据库就行了, 每次用户登录或退出登录的时候, 随登录或退出登录接口传到后端存入数据库即可
    GreatEscape
        12
    GreatEscape  
    OP
       2021-07-28 09:59:45 +08:00
    @tedcon 重点不在于点赞数量,而是用户对该文章的点赞状态,写 DB 同步到缓存会导致用户快速操作时出现缓存不一致的问题。
    waibunleung
        13
    waibunleung  
       2021-07-28 10:43:52 +08:00
    像上面 @hahasong 说的,先界面 UI 实时响应,然后前端 /客户端先把用户点赞过的内容先缓存起来,后端用队列来将点赞数据落地到 DB 。请求用户点赞状态 /计数的时候,返回结果带上一个版本号,前端通过版本号来对比来决定是否+1 或者替换掉服务端的数据,这样是否可以?

    点赞这种东西,不需要强一致性的,只需要保持最终一致就好了。至于数据丢失,肯定会有的,CAP 理论,看你们怎么取舍而已。保证 BASE 可用就好了。个人理解,欢迎友好交流~
    a719031256
        14
    a719031256  
       2021-07-28 13:58:10 +08:00
    我到觉得你先做出来再谈优化,楼主给我的感觉跟我现在带的同事好像,东西没做就想这想那
    ospider
        15
    ospider  
       2021-07-28 14:11:42 +08:00
    我真是特别讨厌叫人「彦祖」这种提问方式,不是每个人都喜欢明星的
    tedcon
        16
    tedcon  
       2021-07-28 16:17:47 +08:00
    @GreatEscape 这个就需要前端控制啊 不管是点赞还是其他操作。前端肯定要有个 state=pending 然后等待 response,成功了才将点赞+1,pending 的时候无法再次点赞。
    shadowfish0
        17
    shadowfish0  
       2021-07-29 01:11:08 +08:00   ❤️ 1
    @ospider 这只是个梗吧,意思和喊帅哥差不多
    ljzxloaf
        18
    ljzxloaf  
       2021-07-29 10:10:08 +08:00
    先更新计数(建议用可持久化的 kv 数据库如 etcd,redis 是用来做缓存的),具体请求先写到消息队列,异步更新到数据库。还有评论啊点赞啊这些东西都是要做频率控制的
    ljzxloaf
        19
    ljzxloaf  
       2021-07-29 10:41:59 +08:00
    @ljzxloaf #18 etcd 好像没有相关的 api,还是用 redis 吧。。注意下可用性
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2624 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 03:50 · PVG 11:50 · LAX 19:50 · JFK 22:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.