V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Newyorkcity
V2EX  ›  问与答

请教一下点赞功能——用户第一次按点赞,第二次按取消,不会赞两次;用 redis 尽量避免对 mysql 的读写——的主流实现思路。谢谢!

  •  
  •   Newyorkcity · 2020-03-14 23:26:08 +08:00 · 1948 次点击
    这是一个创建于 1744 天前的主题,其中的信息可能已经有所发展或是发生改变。
    RT,最近为实习远程面试,自己没有其它可以拿出来,只有一个小项目可说,其中提了实现了点赞功能,面试官就问了我实现方式。

    我的实现方式用 redis 为每个回复存一个 likeit:reply:${reply_id} 的 set,这个 set 中保存点赞了这个回复的账户的 id,所以已经登录的用户在从后台拉取回复的列表的过程中,服务层会在这个过程中对列表中的每个 reply 获取 reply_id,然后向 redis 查询当前用户的 id 是否在集中以及这个回复被赞的数量,保存到这个 reply 实例的一个 @transient 成员 LikeIt 类的 likeit 里。。
    最后前端(前端拿到的当然是 json )就根据这个确定用户有没有点赞过和当前回帖的点赞数。。

    然后面试官就问了下有没有学习过当点赞数可能破万的情况下,有没有更好的方案。如果要提供根据点赞数从高到低展示回复要怎么做。然而我压根没想过(所以说没有深入思考的东西最好还是不要放上去。但真的没东西可放了),就很尴尬。

    所以来 V 站 请教一下,点赞功能主流的实现思路是什么样的?在点赞数可能破万,需要按点赞数进行排序这两种情况下呢?

    谢谢
    4 条回复    2020-03-15 02:22:48 +08:00
    EminemW
        1
    EminemW  
       2020-03-15 01:28:48 +08:00 via iPhone
    点赞数排序用 sort set 存 评论 id 就可以了 点赞数作为每个评论 id 的分数
    EminemW
        2
    EminemW  
       2020-03-15 02:16:44 +08:00 via iPhone   ❤️ 1
    我思考后发现,这个点赞问题在用户量足够大的情况下,会变得很复杂
    这是链接里有微博的设计 https://blog.cydu.net/weidesign/2012/09/09/weibo-counter-service-design-2/

    对于你这个,我觉得需要存几个 key
    1.点赞评论的用户
    2.用户点赞的评论
    3.评论点赞数

    查的时候去判断[用户点赞的评论集合]里有没有该评论。另外考虑到用户可能点赞很多评论,你可以将评论产生的时间做 key 的一部分,查的时候到对应的 key 查用户有没有点赞过该评论。

    重复点赞问题:
    1.从前端限制点赞次数,比如几秒以后才能点
    2.做异步处理,上消息队列
    lxml
        3
    lxml  
       2020-03-15 02:20:51 +08:00   ❤️ 1
    最佳办法是两个 key
    key1 存 userId-tieId 记录用户对某个帖子的状态
    lxml
        4
    lxml  
       2020-03-15 02:22:48 +08:00
    key2 以 tieId 即可,记录帖子的点赞数

    两个 key 之间如果需要维护最终一致,或者 分片打到一起的需求,就调换顺序,把 tieId-userId 这样某个用户查看某一堆贴 ID 都打到一个集群上,加快速度,以及可以扫 tieId* 来定时修复 tieid 的计数器
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   965 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 22:53 · PVG 06:53 · LAX 14:53 · JFK 17:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.