一、应该给Redis分配多少内存空间
八二原则:80%的请求都是访问数据库中同样的20%的数据(热点数据只占20%),所以一般给Redis分配15% - 30%数据总量的内存空间(只保存热点数据,冷数据被访问少,直接到数据库访问)
二、Redis八种内存淘汰机制
三、LRU算法
- 传统LRU算法:底层维护一个双向链表,每个节点存放一个数据,当某个数据被访问时,该节点会被放到链表头部(MRU端),当触发内存淘汰时会先删除链表的尾部(LRU端)。
缺点:每个数据都要一个链表节点维护,内存开销大,频繁移动链表,CPU压力大,无法保证MRU端是热点数据,可能只是刚好在内存淘汰前被访问,之前都是冷数据。 - Redis中的LRU算法:Redis对原生LRU算法进行了改进,会随机挑选5个键加入链表,淘汰其中最久未被访问的(不用为每一个数据维护链表节点,且不用在每次访问数据时移动链表)。
四、推荐使用的淘汰算法
- A) 存在冷热数据的区分时,使用allkeys – lru,可以保留热点数据;
- B) 没有冷热数据区分,每个数据被访问的频率差不多,使用allkeys-random;
- C) 某些数据有置顶需求,不能被淘汰,使用volatile-lru,给置顶数据不设置过期时间,保证不会被淘汰。
五、MySQL脏数据、脏页与Redis的脏数据
- MySQL脏数据:读到的数据是其他事务修改后的数据,但最后事务回滚了,数据库中数据还是原来的值,但是读到的当前数据是事务回滚前修改的值,与数据库中不一致。—客户端读到的数据,而不是存在于MySQL内存页中的数据。
- Redis脏数据:Redis内存中数据的值和当前数据库中不一致。
- MySQL脏页:MySQL内存页上的数据已经更改但是还没刷入到磁盘中。
注:MySQL在清理内存时,会将脏页先更新到数据库,在删除内存中的该数据页
Redis清理内存时,不会将脏数据写到数据库中,所以当数据改变时要同时改变数据库与Redis中该数据的值。
六、保证Redis与MySQL中数据的一致性方案:采用分布式事务
两阶段提交(2PC),三阶段提交(3PC),TCC,消息队列。
以下补充缓存污染与应对的LFU缓存淘汰策略
七、缓存污染与LFU算法:
缓存污染:访问频率低的数据占用大量内存,造成资源浪费。
解决方法:
- LFU淘汰机制
按照数据被访问的频率淘汰内存中的数据,在数据的RedisObject结构体中增加一个lru字段存放数据最近被访问的时间戳以及总共被访问的次数。优先比较被访问的次数低的数据被淘汰,如果访问次数一致,再比较时间戳淘汰最近一次访问时间久远的数据。
LFU算法优化
- 时间戳 + 计数器(优先比较计数器,再比较时间戳);
- 计数器非线性递增(并非访问一次计数器就加一,避免计数器(8bit)越界);
- 计数器衰减机制(避免某些数据短期大量访问后不再被访问,会随着未访问时间的增大降低计数器的数值)。