Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

提出问题

在写前面两个博客的时候,都提到了redis的架构(单体、主从、集群分片),针对不同的架构分析了 Redis 的原子性、数据的一致性,显然架构越复杂,保障数据的一致性和和原子性就越复杂,那复杂架构可以解决单体架构和主从架构不能解决的什么问题?这让我想到在面试腾讯的时候,面试官问我的一个问题,Redis怎么解决热 Key 问题?

场景

在高并发场景中,百万用户同时抢购一万张满减购物券,redis可能会被巨大的流量冲跨,怎么解决这种问题?(这让我想到双十一期间的时候,每天早上10点和晚上8点抢购神仙水,500块一瓶的神仙水谁会不抢呢哈哈哈,但是我抢了三天也没抢到。可见参与的人数有多么多)

热key是什么

单个redis的写入瓶颈是 20000次/秒,读取瓶颈是100000次/秒,在某一个时间段内,对某个key的读写频率超过某个设定的值,导致redis节点的CPU、内存、网络带宽等资源被大量消耗,影响了redis的性能和稳定性。

产生热 key 的原因

  1. 秒杀大促:双11、618、整点秒杀等
  2. 热点数据:热点新闻、热门评论等
  3. 代码逻辑问题:代码逻辑不正确,存在死循环等问题

如果不对热key处理会引发什么问题

  1. 单个redis宕机或性能下降:redis 虽然是基于内存的数据库,其读写耗时远远低于直接访问磁盘上的数据库,但是redis也是存在瓶颈的,查了相关资料得知,单个redis的写入瓶颈是 20000次/秒,读取瓶颈是100000次/秒,当百万请求瞬间请求 单个redis时, 一定会将它冲垮,严重时会导致系统崩溃。

  2. Redis 集群性能下降

    如果高并发请求都落在单个redis上,高流量会冲垮这个redis,在 redis 集群中可能有其他的业务,他们需要的数据均匀的分片在了各个redis上,那么redis宕机也会影响其它的业务,需要对分片的数据进行迁移等操作。

  3. 缓存击穿

    当某些热key恰好过期了,对它进行访问会造成缓存击穿的问题,磁盘数据库扛不住会宕机,严重导致缓存雪崩。

如何有效解决热 key 问题

热 key 问题解决的核心思想

1. redis 崩溃无非是它承受远远超于它能力上限的请求,解决这个问题那就把超过的流量分出去

2. 热key问题本质就是高并发的问题,如何避免让高并发的流量冲垮系统,需要设置多层抵御防线:前端设计(限流,校验。。。)、后端设计(限流,降级,熔断,布隆过滤器。。。)

读多写少场景——分片

redis 架构中有一个集群分片架构,这个架构中存在多个主从结构,每个主节点只负责一部分数据,多个主节点负责的数据的集合才是数据整体,这就是 数据分片。

我们将热点数据均匀地也可以按照一定的比例存放在 redis 集群中,用户请求时根据CRC16 hash(key) % 16384 哈希选择使用哪个redis

写多读少场景——复制全量副本

对于读多写少的场景,我们创建多个热点数据的副本,然后在每个 redis 上存储热key,根据请求用户的ID 哈希选择使用哪个redis读, 为了进一步提高性能, 可以使用读写分离的方式,降低每个数据分片的请求压力,甚至可以不断地增加从节点,但是问题在于从节点增多导致集群架构的复杂度增加,监控和运维成本增加。

注意:采用数据分片,需要更改key,但是内容不变,因为redis集群槽中的数据是根据对key进行哈希来映射的。

智能缓存淘汰策略

选择合适的缓存淘汰算法,根据键的访问频率和时间等指标淘汰不常用的键,为热key腾出更多的空间,让热key留在内存中的时间更久

随机失效时间

给热key加上随机失效时间,避免同时失效时产生又有高并发的请求,导致缓存雪崩

缓存预热

在系统启动或者业务的高峰期来临之前,提前将热key加载到缓存中,减少数据库的查询压力和响应时间

评论