缓存冷启动
当我们使用 redis 的时候,用户请求首先从 redis 集群中访问数据,如果 redis 集群中没有数据的话,则从数据库中查询数据,然后返回给用户。
用户访问 --> reids cluster --> mysql
有没有想过这种方式会有什么样的问题?有什么风险?
- 首先,应用系统新上线的时候,此时 redis 集群中是没有数据的,这个时候如果有大量的请求过来的,那么这些请求都会直接访问数据库。这个时候,在高并发的情况下,mysql 数据库很可能会挂掉,redis 集群中也没有数据,此时系统处于一个不可用的状态。
- 其次的话,在系统运行的过程中,redis 集群突然宕机了,内存中的数据没有了,并且持久化的数据也不可用的话,即使 redis 集群故障后重启,也无法恢复 redis 中的数据。这时,在高并发情况下,mysql 数据库也可能挂掉,系统处于不可用状态。
redis 集群启动后,没有任何的缓存数据,可以称为 redis 的冷启动。
那么如何解决这个问题呢?其方案就是缓存预热。
缓存预热
故名之意,缓存预热就是在 redis 启动的时候,就开始往 redis 中写了数据,然后再给应用提供服务。而不是在应用访问的时候才开始往 redis 中写数据。
那么启动的时候,应该往 redis 中写入什么要的数据呢?
应该根据当天的具体的访问情况,进行实时的统计出访问量频率较高的数据,即热数据,比如热门商品,热门博客等,把这部分数据提前写入 redis 集群中。我们不需要把所有的数据都写入 redis 中,也没有这个必要,一是数据量会很大,写入的数据会很慢,二是访问量不大的数据也没有必要写入 redis 中。
如果热数据比较多的话,我们可以启动多个服务并行读取数据去写入 redis 集群,进行分布式的缓存预热。
当把热数据写入 redis 集群后,才开始对处提供服务。那么这样,大部分的请求都会走 redis 集群,而不需要访问 mysql 数据库。
技术实现方案
现在,我们知道,需要进行缓存预热。但出现了一个新的问题,那就是如何获得热点数据?
可以参考以下的实现方案:
- 首先,通过 nginx + lua 的方式,把访问流量数据上报到 Kafka,也可以是其它的 mq 队列。
- 然后使用实时计算框架(如 storm 、spark streaming、flume)从 kafka 中消费访问流量数据,实时计算出访问频率高的数据,这里统计出来的可能只会有编号信息,如商品编号或博客编号等。
- 最后,根据编号从 mysql 数据库中查询出具体的信息,写入 redis,开始提供服务。