Skip to content

Latest commit

 

History

History
160 lines (86 loc) · 4.94 KB

点赞系统设计.md

File metadata and controls

160 lines (86 loc) · 4.94 KB

用户与Feed的点赞:

实现功能

  1. 显示点赞数量
  2. 判断用户是否点过赞,用于去重,必须的判断
  3. 显示个人点赞列表,一般在用户中心
  4. 显示文章点赞列表

实现

  • MySQL方案

    -- 文章表
    
    create table post {
    
            post_id int(11) NOT NULL AUTO_INCREMENT,
    
            ......
    
            star_num int(11) COMMENT '点赞数量'
    
    }
    
    -- 用户表
    
    create table user {
    
            user_id int(11) NOT NULL AUTO_INCREMENT,
    
            ......
    
            star_num int(11) COMMENT '点赞数量'
    
    }
    
    -- 点赞表
    
    create table star {
    
            id int(11) NOT NULL AUTO_INCREMENT,
    
            post_id,
    
            user_id,
    
            ......
    
    }
    

    常用的查询:

    查询用户点赞过的文章 select post_id from star where user_id=?

    查询文章的点赞用户 select user_id from star where post_id=?

    点赞数量可以通过定时异步统计更新到post和user 表中。

    数据量不大的时候,这种设计基本可以满足需求了,

    缺点:

    数据量大时,一张表在查询时压力巨大,需要分表,而不论用post_id还是user_id来hash分表都与我们的需求有冲突,唯一的办法就是做两个表冗余。这增加了存储空间和维护工作量,还可能有一致性问题。

  • Redis方案

    采用redis有两种用途,一种是storage,一种是纯cache,需要+mysql一起。纯cache就是把数据从mysql先写入redis,用户先读cache,miss后再拉取MySQL,同时cache做同步。

    场景a :显示点赞数量

    //以文章id=888为例   使用String结构自增计数
    127.0.0.1:6379[2]> set star:tid:888 898 //设置点赞数量 
    OK 
    127.0.0.1:6379[2]> incr star:tid:888 //实现数量自增 (integer) 
    899

    场景b:点赞去重,避免重复点赞

    场景c:一般在用户中心,可以看到用户自己的点赞列表

    场景d:文章的点赞列表,类似场景b,以文章id为key

    //以文章id=888为例 
    127.0.0.1:6379[2]> sadd star:list:tid:888 123 456 789  //点赞uid列表 (integer) 
    3 
    127.0.0.1:6379[2]> sismember star:list:tid:888 456  //判断是否点赞 (integer) 
    1

    也可以用Hash结构

    key: hash_{post_id} field: user_id value: timestamp

    如果value只存时间戳,说明key里记录的都是有效点赞,取消的则从key里删除了,并不记录状态。

    1. 显示点赞数量:统计文章Hash Key的数量,或者单独记一个Key随着用户点赞和取消点赞自增自减。
    2. 判断用户是否点过赞,用于去重,必须的判断:HEXISTS hash_{post_id} user_id
    3. 显示个人点赞列表,一般在用户中心:这个要单独记录用户的Key了,可以是Set结构也可以同样的是Hash结构。
    4. 显示文章点赞列表:点赞用户列表,只要取出hgetall hash_{post_id} 的所有数据排序分页取出即可。

Redis实现点赞功能模块 - 掘金 (Redis存的Key太简单,都集中在一个key里了)

点赞功能,用 MySQL 还是 Redis ?-java小组-二十次幂

基于redis的点赞功能设计 36663951的博客-CSDN博客_redis实现点赞功能设计

人与人的点赞:

点赞模块设计 - Redis缓存 + 定时写入数据库实现高性能点赞功能 - 掘金

通用点赞设计思路 - 掘金

点赞计数:

点赞、计数系统的设计,以及图数据的存储选型 - 简书

微博点赞演化

微博关系服务与Redis的故事 - InfoQ

新浪微博开放平台Redis实战

WeiDesign微博计数器的设计 velocity · Cydu's Blog

[WeiDesign]微博计数器的设计(下) · Cydu's Blog

需求实现:

  • 查询用户关注列表:hgetAll uid.following ,then sort
  • 查询用户粉丝列表:hgetAll uid.follower,then sort
  • 查询用户双向关注列表:hgetAll uid.bifollow,then sort
  • 判断两个用户关系:hget uidA.following uidB && hget uidB.following uidA

hgetAll 在 hash size 较大的场景下慢请求比例较高问题:

  • 调整了 hash-max-zip-size,节约了 1/3 的内存
  • 在 Redis 前面又挡了一层 memcache,用来抗 hgetAll 读的问题

容量增长的问题:

uid hash 成 16 个端口,每台 64G 内存的机器上部署 2 个端口,每个业务 IDC 机房部署一套。