文章目录

  • 引入
  • 使用Mysql实现点赞功能
  • 使用Redis实现点赞功能
  • 使用什么数据格式最合适?
  • 方案


引入

最近遇到一个需求,就是做联盟链做存证上,部分交易对外公开,或者是对指定人可见。之前一直在思考用Mysql怎么存合适,想来想去也没找出个合适的办法。
点赞功能场景和上面的需求是一样的,我就借这个简单一些的点赞功能来理清下思路把。

我们先看点赞功能的需求:

  • 显示点赞数量
  • 判断用户是否点过赞,用于去重,必须的判断
  • 显示个人点赞列表,一般在用户中心
  • 显示微博/文章的点赞列表

java点赞 redis JAVA点赞功能_redis


微博这是头部的顶级流量,后端肯定是有复杂架构的,我们今天暂时只讨论大众化的方案。

使用Mysql实现点赞功能

采用mysql做点赞功能的记录的话,一般是要三个表:

  1. 用户表。
  2. 文章表。
  3. 用户-文章关联表(点赞表)。

那么点赞功能常用的查询就是:

  • 查询某一篇文章的点赞的用户:
    select user_id from star where post_id=?
  • 查询某一用户点赞过的文章:
    select post_id from star where user_id=?

虽然我们这里讨论的是大众化的方案,但不是说的数据量小,只是说的架构简单。

我们思考下,如果使用单表查询,一个表肯定是支撑不住的,即使建立了两个索引数据库表的压力也是很大的。
这时只能考虑分库分表,那么怎么分表成为了一个难题:是按照用户id分还是文章id分呢?因为不用的查询,有时涉及到分表后的单表,有时涉及到多表。这样Hash起来是有冲突的
那么只能考虑做两个分表的冗余,不过这增加了存储空间和维护工作量,还可能有一致性问题。

所以,使用mysql来做点赞功能,不是很好。

使用Redis实现点赞功能

由于点赞这种动作很随意,很多人看到大拇指就想点,所以数据量增长很快,数据规模上来后,对mysql读写都有很大的压力,这时就要考虑redis了。

采用redis有两种用途,一种是storage,一种是cache

使用什么数据格式最合适?

Redis具有丰富的数据类型,支持字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。

java点赞 redis JAVA点赞功能_Redis_02

Redis 内部使用一个 redisObject 对象来表示所有的 key 和 value。type 表示一个 value 对象具体是何种数据类型,encoding 是不同数据类型在 Redis 内部的存储方式。

比如:type=string 表示 value 存储的是一个普通字符串,那么 encoding 可以是 raw 或者 int。

  • String 是 Redis 最基本的类型,一个 Key 对应一个 Value。Value 不仅是 String,也可以是数字,也可以是对象的序列化。
  • Hash是一个键值(key-value)的集合。Redis 的 Hash 是一个 String 的 Key 和 Value 的映射表,Hash 特别适合存储对象。
  • List,List 列表是简单的字符串列表,按照插入顺序排序。Redis 提供了 List 的 Push 和 Pop 操作,还提供了操作某一段的 API,可以直接查询或者删除某一段的元素。
  • Set和ZSet不做赘述。当你需要一个有序的并且不重复的集合列表,那么可以选择 Sorted Set 结构。

我们可以看到使用点赞列表,最合适的方式还是Hash或者List了。如果需要记录点赞人和被点赞人,还有点赞状态(点赞、取消点赞),还要固定时间间隔取出 Redis 中所有点赞数据,使用Hash能够保存key和value,算是更合适的了。

关于底层编码的实现方案,我以后的文章会做介绍。

方案


  • 使用redis作为storage的方案:

场景a :显示点赞数量
在点赞的地方,只是显示一个点赞数量,能区分用户是否点赞过,一般用户不关心这个列表,这个场景只要一个数字就可以了,当数量比较大时,一般显示为"7k" ,“10W” 这样。

以文章id为key。

//以文章id=888为例 
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:点赞去重,避免重复点赞
要实现这个需求,必须有文章点赞的uid列表,以tid为key。

场景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

redis作为storage使用时,一定要做好数据的持久化,必须开启 rdb 和 aof,这会导致业务只能使用一半的机器内存,所以要做好容量的监控,及时扩容。


  • 使用redis做为cache的方案:

基于 SpringCloud, 用户发起点赞、取消点赞后先存入 Redis 中,再每隔两小时从 Redis 读取点赞数据写入数据库中做持久化存储。

这一点,以后有机会再做详细介绍。