- 显示点赞数量
- 判断用户是否点过赞,用于去重,必须的判断
- 显示个人点赞列表,一般在用户中心
- 显示文章点赞列表
-
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做同步。
//以文章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
//以文章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里删除了,并不记录状态。
- 显示点赞数量:统计文章Hash Key的数量,或者单独记一个Key随着用户点赞和取消点赞自增自减。
- 判断用户是否点过赞,用于去重,必须的判断:HEXISTS hash_{post_id} user_id
- 显示个人点赞列表,一般在用户中心:这个要单独记录用户的Key了,可以是Set结构也可以同样的是Hash结构。
- 显示文章点赞列表:点赞用户列表,只要取出hgetall hash_{post_id} 的所有数据排序分页取出即可。
Redis实现点赞功能模块 - 掘金 (Redis存的Key太简单,都集中在一个key里了)
点赞功能,用 MySQL 还是 Redis ?-java小组-二十次幂
基于redis的点赞功能设计 36663951的博客-CSDN博客_redis实现点赞功能设计
点赞模块设计 - 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 机房部署一套。