type
status
date
slug
summary
tags
category
icon
password
1、Redis键空间
默认情况下,Redis中有16个数据库,编号从0-15,每个Redis数据库使用一个redisDb对象来表示,每个redisDb对象实际上是一个dict结构的数据集合。
其中dict保存了该db中的所有键值对。键值对中键是一个字符串对象,每个值可以是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象在内的任意一种 RedisObject。
redis通过全局哈希表保存所有的key值,所以查找key的时间为O(1)。redis一下次写入太多数据有可能会产生哈希冲突,全局哈希表也是通过渐进式rehash来解决大量hash冲突的问题
2、过期删除策略
我们可以设置Redis中缓存的key的过期时间。过期删除策略就是指当Redis中缓存的key过期了Redis会如何删除,通常有以下策略:
过期策略 | 描述 | 优点 | 缺点 |
定时删除 | 每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。 | 节省内存 | cpu不友好,频繁的删除可能会影响性能 |
惰性删除 | 只有当访问一个key时,才会判断该key是否已过期,过期则清除。 | 内存不友好,可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。 | 节省CPU资源 |
定期删除 | 每隔一段时间,扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。 | 前两者的一个折中方案,使得CPU和内存资源达到最优的平衡效果。 | ㅤ |
Redis同时使用了惰性过期和定期过期两种过期策略:
- 每当我们设置一个key的过期时间时,Redis就会将该key带上过期时间存放到一个过期dict中。
- 当我们查询一个键时,Redis便首先检查该键是否存在过期字典中,如果存在,那就获取其过期时间。然后将过期时间和当前系统时间进行比对,比系统时间大,那就没有过期;反之判定该键过期。
- Redis 默认会每100ms扫描一次,但不会遍历过期dict中所有的 key,而是采用了一种简单的贪心策略。
- 从过期字典中随机 20 个 key。
- 删除这 20 个 key 中已经过期的 key。
- 如果过期的 key 比率超过 1/4,那就重复步骤 1。
3、内存淘汰策略
虽然我们有过期策略来淘汰已过期的数据,但是如果大量数据过期时间还没到,但此时内存已经快被占满了,我们就需要通过内存淘汰策略选择淘汰哪些数据。
内存淘汰策略 | 描述 |
noeviction | 不淘汰数据,默认策略。 |
volatile-ttl | 在设置了过期时间的键值对,根据过期时间的先后进行删除,越早过期的越先被删除。 |
volatile-random | 在设置了过期时间的键值对中,进行随机删除。 |
volatile-lru | 在设置了过期时间的键值对,使用LRU算法筛选,删除最近最长时间不使用的key。redis对LRU的优化:每次随机选出N个数据,比较该N个数据的最近访问的时间戳,然后最长时间不访问的数据。 |
volatile-lfu | 在设置了过期时间的键值对,使用LFU算法选择,删除最近使用次数最少的key。 |
allkeys-random | 从所有键值对中随机选择数据进行删除。 |
allkeys-lru | 在所有数据中进行筛选,使用LRU算法,删除最近最长时间不使用的key。 |
allkeys-lfu | 在所有数据中进行筛选,使用LFU算法,删除最近使用次数最少的key。 |
这八种策略大体分为「不进行数据淘汰」和「进行数据淘汰」两类策略。针对「进行数据淘汰」这一类策略,又可以细分为「在设置了过期时间的数据中进行淘汰」和「在所有数据范围内进行淘汰」这两类策略。
LRU和LFU算法比较:
- LRU(Least Recently Used):淘汰最长时间未被使用的页面,强调的是最近访问时间。链表按访问时间进行排序,表头是最近访问的页面。如果访问命中了页面,就把页面移动到链表表头;如果没有命中就从表尾删除页面,然后把新页面放在表头,是比较符合正常思维逻辑的算法。
- LFU(Least Frequently Used):淘汰最近被访问次数最少的页,强调的是最近访问频率。链表按访问次数进行排序,表头是访问次数最多的页面。如果访问命中了页面,就把页面的访问次数加一,此时如果该页面的访问次数大于前一个页面就互相交换位置;如果没有命中页面就从表尾删除数据。这种算法有一个明显的问题:如果某页面开始访问次数较多,但后面没有再被访问,这些页面无法被删除。所以LFU算法用的比较少。
淘汰策略选择建议:
- 优先使用
allkeys-lru
策略。这样,可以充分利用LRU这一经典缓存算法的优势,把最近最常访问的数据留在缓存中,提升应用的访问性能。如果你的业务数据中有明显的冷热数据区分,我建议你使用 allkeys-lru 策略。
- 如果业务应用中的数据访问频率相差不大,没有明显的冷热数据区分,建议使用
allkeys-random
策略, 随机选择淘汰的数据就行。
- 如果你的业务中有置顶的需求,比如置顶新闻、置顶视频,那么,可以使用
volatile-lru
策略,同时不给这些置顶数据设置过期时间。这样一来,这些需要置顶的数据一直不会被删除,而其他数据会在过期时根据 LRU规则进行筛选。
- Author:mcbilla
- URL:http://mcbilla.com/article/f073ccca-28a3-4492-9cd8-05380ac83f4a
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!