1. 为什么 Redis 需要存热点数据?
在大数据场景下,数据库(MySQL)查询通常比缓存(Redis)慢得多,如果所有请求都直接查询 MySQL,不仅查询速度慢,还可能拖垮数据库。因此,我们希望 Redis 只存最常访问的数据,减少 MySQL 访问次数,提高系统吞吐量。
2. 使用 LRU 机制自动淘汰冷数据
LRU(Least Recently Used,最近最少使用) 算法是一种常见的缓存淘汰策略,它会自动删除最近最少被访问的数据,从而保证 Redis 中的数据始终是热点数据。
Redis 提供了 allkeys-lru
策略,它会在所有的 key 中选择最近最少使用的数据进行淘汰,确保高频访问的数据留在 Redis 里。
配置方式:
redis.conf 配置:
maxmemory-policy allkeys-lru
或者在 Redis 运行时修改:
CONFIG SET maxmemory-policy allkeys-lru
这样,每当 Redis 达到最大内存限制时,就会自动淘汰最久未被访问的数据,确保 Redis 里的数据始终是热点数据。
3. 控制 Redis 的数据大小
Redis 内存大小必须合理分配,确保 Redis 只存储 20 万条数据。
估算 Redis 需要的内存大小假设:
- 总共占用
200 × 200000 = 40 MB
我们可以限制 Redis 最大内存,例如:
CONFIG SET maxmemory 50mb
这确保 Redis 不会无限增长,避免 OOM(内存溢出)问题。
4. 数据访问频率优化
如果 MySQL 有 2000 万数据,而 Redis 只能存 20 万数据,我们需要确保 Redis 里都是被频繁访问的数据。除了 LRU 策略,我们还可以结合 本地缓存统计
和 定期同步策略。
方案 1:利用 MySQL 访问日志统计热点数据
可以通过 MySQL 记录哪些数据查询频率最高,然后批量更新 Redis。
示例 SQL 查询 MySQL 热点数据:
SELECT data_id, COUNT(*) as visit_count
FROM access_logs
WHERE timestamp > NOW() - INTERVAL 1 HOUR
GROUP BY data_id
ORDER BY visit_count DESC
LIMIT 200000;
这样,我们可以定期(如每 5 分钟)同步这些数据到 Redis,保证 Redis 中的都是最常访问的数据。
方案 2:使用 Redis 计数器统计热点数据
Redis 的 ZSET
(有序集合)可以记录数据的访问频率。
ZINCRBY data_access_count 1 data_id
然后定期移除低访问频率的数据,仅保留排名前 20 万的数据:
ZREMRANGEBYRANK data_access_count 0 -200001
这样 Redis 只存储访问次数最多的数据。
5. 结合 TTL 机制淘汰过期数据
如果热点数据有时间敏感性,可以利用 Redis expire
机制,让数据在过期后自动删除。
SET key value EX 3600 # 1小时后过期
这样可以避免 Redis 长期存储已经不再热门的数据。
6. 结合业务优化缓存
除了 Redis 本身的机制,还可以通过 业务逻辑优化缓存:
- 热点数据分级缓存:比如把 10% 超级热点数据放入 Redis,其他数据走本地缓存(如 Guava Cache)
- 批量查询 MySQL:减少缓存未命中时对数据库的压力
- 异步刷新缓存:避免 Redis 失效后,数据库被突然冲击
7. 总结
要保证 Redis 里只存 20 万条热点数据,我们可以采取以下措施:
- 启用 allkeys-lru 策略,自动淘汰冷数据。
- 限制 Redis 最大内存,避免超出 20 万数据。
- 用 MySQL 访问日志或 Redis 计数器统计热点数据,定期同步到 Redis。
通过这些手段,我们就能确保 Redis 中的数据始终是访问最频繁的热点数据,提升系统性能。