从一个小需求感受Redis的独特魅力( 二 )


从一个小需求感受Redis的独特魅力文章插图
可以看到 , 我们的这个key-field-value没有设置过期时间 , 因为可以认为这个key是一个热点key , 对于热点key我们的处理方式是 , 永久有效或过期时间尽量长一点 。
【从一个小需求感受Redis的独特魅力】第四版 缓存预热防止缓存击穿
另一个关于缓存的问题 , 那就是缓存击穿 。
何为缓存击穿?假如该功能在前期宣传力度比较大 , 或预计该功能上线后点击量比较大的话 , 那么在功能上线后很可能就会一瞬间大量用户来点击这个功能 , 因为我们前面的逻辑是首次进入该功能的用户展示协议页 , 我们的后台处理虽然加了redis缓存 , 但是新上的功能所有用户都没有点过 , 那么redis里就没有缓存 , 是不是所有用户的请求都落到数据库了?一旦瞬间流量非常大 , 数据库安全性就存在隐患 , 有被搞垮的可能 。
从一个小需求感受Redis的独特魅力文章插图
这个问题就是可以理解为缓存击穿 。 (实际的缓存击穿是某个key在缓存里不存在或是失效后 , 某一瞬间很多请求都来访问这个key , 都判定为redis里没有这个key , 就都去查库 。 )
所以怎么解决呢?我们可以在该功能上线前 , 提前将需要做缓存的数据放入redis , 即缓存预热 。
如何预热?将所有用户的信息都放到redis.举个栗子(也许不是最佳的) , 我们使用Redis的hash数据结构 , key-field-value 。 key我们可以固定一个字符串如coderTreeHole_Agreement_Check , field我们可以用客户号(唯一) , value是个标志位 , 用0代表没同意过协议 , 1代表同意过 。 一般在电商大促前都会对热点key进行预热 , 不然真的扛不住 。
从一个小需求感受Redis的独特魅力文章插图
and , 用户量很大的时候redis里的coderTreeHole_Agreement_Check这个key是不是很大?在redis集群部署模式下 , 这个key是不是都放在一个节点上?why?
redis3.0上加入了cluster模式 , 实现的redis的分布式存储 , 也就是说每台redis节点上存储不同的内容 。 在redis的每一个节点上 , 都有这么两个东西 , 一个是插槽(slot) , 它的的取值范围是:0-16383 。 还有一个就是cluster , 可以理解为是一个集群管理的插件 。 当我们的存取的key到达的时候 , redis会根据crc16的算法得出一个结果 , 然后把结果对16384求余数 , 这样每个key都会对应一个编号在0-16383之间的哈希槽 , 通过这个值 , 去找到对应的插槽所对应的节点 , 然后直接自动跳转到这个对应的节点上进行存取操作 。
看了上面这段话 , 明白了吧 。 那对于这个大key而且是热点key的请求 , 是不是都落到某一个redis节点上了?大key会带来很多问题 , 篇幅原因以后再来细说 , 跑题了 。。。
针对这个需求 , 你还有什么方法防治缓存击穿?
第五版 消息队列削峰填谷
可以看到我们上面的设计其实都是实时对数据库进行操作的 。
例如 , 当用户点了同意 , 前端就调后台的recordAgree方法将该记录记录到数据库 , 即这条记录是立马插入到数据库的 。
如果刚上线这个功能 , 大量用户同时点这个功能 , 并发量大的话 , 请求走到后台 , 那么写库的操作就非常多 , 数据库连接数突然激增 , 数据库会顶不住吧 。
所以为避免流量集中落到数据库 , 此时我们可以使用消息队列MQ 。 将插入操作的请求发往消息队列 , 使插入操作以一定的速率到数据库执行 , 使得对数据库的请求数尽量平滑 , 消息发给消息队列立即返回给前端成功 , 不用等待插库完成 , 用MQ实现了异步解耦 , 削峰填谷 。
从一个小需求感受Redis的独特魅力文章插图
到这你是不是忍不住说设计的真赞~~
从一个小需求感受Redis的独特魅力文章插图
另外MQ的使用注意的点还是非常多的 , 如:消息队列的消息重复消费问题 , 顺序问题 , 事务消息等 。
总结对于这个需求设计到哪种程度取决于你的用户量和并发量 , 如果是像双十一那样 , 肯定是要用消息队列的 , 那一般小的例如 , 用户量1千万 , 日活10万 , 请求最集中的也就是中午9-12点 , 下午13-17点吧 , 差不多8个小时 , 平均一个小时1.25万 , 用户都来点这个功能的话 , 每分钟208 , 每秒3.5 , 算不上高并发 , 数据库完全扛得住 。
总结一下 , 这个需求我们用到的知识点(敲黑板) , redis数据缓存 , redis缓存穿透 , 缓存击穿 , 热点key问题 , redis大key问题(没具体讲) , 消息队列异步解耦等 。