目录
-
- 一、前言
- 二、业务分析
- 三、Redis数据结构选择分析和实现
-
- [3.1、三个数据缓存都分别使用 字符串 结构计数器存储对应数量值](#3.1、三个数据缓存都分别使用 字符串 结构计数器存储对应数量值)
- [3.2、三个数据缓存使用一个 Hash 结构存储](#3.2、三个数据缓存使用一个 Hash 结构存储)
- [3.3、阅读量使用字符串结构计算器,收藏和点赞分别使用 Set 集合存储](#3.3、阅读量使用字符串结构计算器,收藏和点赞分别使用 Set 集合存储)
- 四、总结
一、前言
在博客中会显示文章阅读量、收藏、点赞数量这些值都是经常变化的,收藏和点赞用户还是可以取消的会记录用户标记状态。如果每一次用户查看博客都从数据库中检索这些数据那数据库开销是非常大的,这个时候就需要使用到缓存来存储这些信息。
需要看Redis命令可以查看:
Redis常用命令集:https://blog.csdn.net/weixin_44606481/article/details/133672258
二、业务分析
在这三个数据中,阅读量和用户没有关系不用存储用户和文章的关系,但是收藏和点赞和用户就是有关的,每个用户对同一篇文章只能收藏一次和点赞一次,并且可以取消,是有状态的数据,针对这两种不同类型的业务选择的数据结构也不同,实现方法也有很多种这里分析其中几个。
三、Redis数据结构选择分析和实现
这里不会过多分析数据库相关方面设计,重点分析Redis中应该如何存储这些数据可以高效使用,阅读量是一个持续自增的值和其它业务无关,在数据表中用一个字段记录即可,但是收藏和点赞需要一个对应业务和用户的关联表来记录关系,每次查询时都要查询关联表统计出文章被多少用户收藏和点赞,还要判断当前查看文章的用户是否有收藏和点赞,当然数量信息我们也可以存储某个记录表中,但是每次查询都打到数据库压力还是挺大的,数据库资源很宝贵,这些信息统计好后存储在缓存中会是一个不错的选择。
3.1、三个数据缓存都分别使用 字符串 结构计数器存储对应数量值
鉴于上面所说,这里我们将阅读量、收藏、点赞数量使用三个字符串结构存储,不同业务操作对应key即可,还要注意这些数据入数据库操作。
-
1、Key定义规则
- 阅读量key:article:readcount:文章id
- 收藏数量key:article:collectcount:文章id
- 点赞数量key:article:likecount:文章id
-
2、代码实现
这里直接使用计数器操作即可,每次有对应操作只要对具体key做自增或者自减即可,假设文章id=1
bash## 文章每次被阅读,文章阅读量自增1 127.0.0.1:6379> incr article:readcount:1 ## 文章每次被收藏,文章收藏数量自增1 127.0.0.1:6379> incr article:collectcount:1 ## 文章每次被点赞,文章点赞数量自增1 127.0.0.1:6379> incr article:likecount:1 ## 文章每次被取消收藏,文章收藏数量自减1 127.0.0.1:6379> decr article:collectcount:1 ## 文章每次被取消点赞,文章点赞数量自减1 127.0.0.1:6379> decr article:likecount:1 ## 获取文章阅读量、收藏、点赞数量 127.0.0.1:6379> get article:readcount:1 127.0.0.1:6379> get article:collectcount:1 127.0.0.1:6379> get article:likecount:1
-
3、优点
- 实现简单、能减轻统计查询时的数据库压力
-
4、不足点
- 需要使用非常多的key,一篇文章就要使用三个key,而且每次查看文章都需要请求Redis三次才能获取到这三个数量值,对Redis资源开销比较大,可以使用Hash结构优化。
3.2、三个数据缓存使用一个 Hash 结构存储
针对3.1中因为需要使用非常多的key,一篇文章就要使用三个key,而且每次查看文章都需要请求Redis三次才能获取到这三个数量值,对Redis资源开销比较大,这里可以使用Hash结构优化。
-
1、Key定义规则
- 文章阅读、收藏、点赞Hash结构 key:article:count:文章id
- Hash结构中阅读量key:readcount
- Hash结构中收藏数量key:collectcount
- Hash结构中点赞数量key:likecount
-
2、代码实现
这里直接Hash 结构操作即可,每次有对应操作只要对具体Hash结构中的key做自增或者自减即可,假设文章id=1
bash## 文章每次被阅读,文章阅读量自增1 127.0.0.1:6379> hincrby article:count:1 readcount 1 ## 文章每次被收藏,文章收藏数量自增1 127.0.0.1:6379> hincrby article:count:1 collectcount 1 ## 文章每次被点赞,文章点赞数量自增1 127.0.0.1:6379> hincrby article:count:1 likecount 1 ## 文章每次被取消收藏,文章收藏数量自减1 127.0.0.1:6379> hincrby article:count:1 collectcount -1 ## 文章每次被取消点赞,文章点赞数量自减1 127.0.0.1:6379> hincrby article:count:1 likecount -1 ## 获取文章阅读量、收藏、点赞数量 127.0.0.1:6379> hgetall article:count:1
-
3、优点
- 相比于3.1中实现简单、能有效减低Redis资源开销
-
4、不足点
- 还是有一点问题没有解决,如果要查询阅读用户和文章的收藏和点赞关系,那么还是要查询数据库,数据库压力还是比较大,在下面3.3中会针对这个问题使用 Set 集合解决。
3.3、阅读量使用字符串结构计算器,收藏和点赞分别使用 Set 集合存储
为了解决查询阅读用户和文章的收藏和点赞关系,还需要查询数据库问题,这里采用Set集合来存储文章收藏点赞和用户的关联关系。
-
1、Key定义规则
- 阅读量key:article:readcount:文章id
- 收藏数量Set key:article:collectuser:文章id
- 点赞数量Set key:article:likeuser:文章id
-
2、代码实现
阅读量还是普通结构和3.1一致,收藏和点赞使用Set集合存储文章和用户对应关系,每次收藏点赞时将用户ID加入到对应Set集合中,假设文章id=1。
bash## 文章每次被阅读,文章阅读量自增1 127.0.0.1:6379> incr article:readcount:1 ## 文章每次被收藏,将用户ID加入到文章收藏的Set集合中,假设用户ID为1001 127.0.0.1:6379> sadd article:collectuser:1 1001 ## 文章每次被点赞,将用户ID加入到文章点赞的Set集合中,假设用户ID为1001 127.0.0.1:6379> sadd article:likeuser:1 1001 ## 文章每次被取消收藏,将用户ID从文章收藏的Set集合中删除 127.0.0.1:6379> srem article:collectuser:1 1001 ## 文章每次被取消点赞,将用户ID从文章点赞的Set集合中删除 127.0.0.1:6379> srem article:likeuser:1 1001 ## 获取文章阅读量、收藏、点赞数量 ### 获取阅读量 127.0.0.1:6379> get article:readcount:1 ### 获取收藏数量 127.0.0.1:6379> scard article:collectuser:1 ### 获取点赞数量 127.0.0.1:6379> scard article:likeuser:1 ## 获取当前阅读用户是否收藏、点赞当前文章 ### 获取用户是否收藏当前文章 127.0.0.1:6379> sismember article:collectuser:1 1001 ### 获取用户是否点赞当前文章 127.0.0.1:6379> sismember article:likeuser:1 1001
-
3、优点
- 对于阅读量、收藏、点赞相关所有的查询操作都可以通过Redis获取,大大降低了数据库压力,并且还会再Redis中维护文章和用户的收藏、点赞关系,查询用户是否收藏点赞也不要再去查询数据库。
-
4、不足点
- 事情都有两面性,使用Redis来缓存这些信息虽然能大大提升系统整体性能,但是可能出现缓存与数据库数据不一致问题,还有缓存过期时间问题,如果一篇文章一个月才被访问一次那么不可能一直缓存这篇文章的信息,需要设置一个删除时间,要想比较完善的实现那么设计这个功能复杂度是成倍增长的。
四、总结
实现方式还有很多,比如在3.3中还能使用Hash结构去维护阅读量、收藏、点赞的数量信息,收藏和点赞与用户关联信息放入对应Set集合中,这样就不用每次都去不同的key中获取对应数量信息了,一个Hash全搞定,最终要选择什么方案还是结合项目实际情况来决定的。