前言
Redis的基本类型和淘汰策略
一、基本类型
String
String类型是包含很多种类型的特殊类型,并且是二进制安全的。比如序列化的对象进行储存,比如一张图片进行二进制储存,比如一个简单的字符串数值等等,最大能存储512M。
set key value :设置key的值为value
get key : 获取key的value
setnx key realValue :若key不存在,set key的值为realValue
setex key time(秒) realValue :设置key的值为value,并设置time的有效期,当超过有效期销毁realValue
由于存储格式是二进制的,可使用setbit来进行对位的操作
setbit k offset v: 设置或清除指定偏移量(offset)上的位(bit)
set test a //在此set k->v 为 test->a
get test ->a //所以get test 得到a
//通过setbit 可以更改test的val
//‘a'的ASCII码是 97。转换为二进制是:01100001,
//‘b‘的ASCII码是 98。转换为二进制是:01100010,
//所以将a改为b就是将偏移量非0的第6位改为1,第7位改为0
setbit test 6 1
setbit test 7 0
get test ->b //所以get test 得到b,通过二进制将数据进行了更改
由此可以延伸出bloomgfilter,将val进行hash计算,得到int[]数组,通过setbit遍历出数组set为1,数组值默认为0.
应用场景: 缓存功能,提高查询效率;计数器,实现计数;共享Session,处于负载均衡考虑,将用户信息均衡到不用的服务器上;限速,限制用户高频登陆发请求;bloom filter
Hash
String类型的field和val的映射表,hash特别适合用于存储对象,每个hash可以存储 40亿的键值对。
hmset user name tom : hmset进行属性设值
hmset user age 15 sex man:hmset可进行批量存储多个键值
hmget user name age sex : hmget可进行批量获取多个键值对
hsetnx user name tom : 同String的setnx
hexists user name: 判断key是否存在
hlen user : 返回hash中所有键的数值。
hkeys user : 返回hash中的所有键。
hvals user : 返回Hash中所有的值。
hgetall user : 返回Hash中所有的键和值。
hincrby user age increment : 为指定字段的整数值加上增量 increment 。
hdecrby user age decrement : 为指定字段的整数值减去increment 。
应用场景: 购物车,用户id作为key,商品id作为filed,商品数量为val
List
List用来存储多个有序的字符串,元素可以重复,每个列表可以存储40亿元素
lpush+lpop 栈,左加入,左弹出
lpush+rpop 队列,左加入,右弹出
lpush+brpop 消息队列。brpop,当队列中没有元素会阻塞
常用于实现消息队列
Set
是String类型的无序集合,集合元素是唯一的,不能重复,集合通过Hash表实现,所以添加、删除、查询的时间复杂度都是O(1)。
sadd set value1 value2 : 将value1,value2多个元素加入到set中
scard set : 查看set成员数
sdiff set1 set2 : 返回set1和set2的差异
sinter set1 set2 : 返回几个差异
使用场景: 因为不能重复,使用差集、交集实现共同用户兴趣爱好
ZSet
集合元素唯一,不可重复,每个元素关联一个double的类型的分数,redis通过这个分数对集合中元素进行大小排序
因为有序,使用跳表
实现,提高查询效率
跳表
一个链表在查询的时候避免依次遍历,按照一定规则抽取一般元素构成另一链表2,在查询的时候,先于抽取出的2链表进行定位比较,然后通过2链表的位置指向找到1链表的位置,使用空间换时间,提高了查询的效率
为了避免插入新节点后的重新调整
跳表不要求每个链表之间有严格的对应关系
为每个节点随机抛出一个层数‘
使用场景: 延时队列,将分数作为时间戳来进行判断
Hyperloglog
提供不精确的去重计算,内存占用小,只需要12k(1210241024)能存储2^64个数据
计数存在一定的误差,误差率整体较低。标准误差为 0.81%
使用场景: 可用作热点页面的去重访问量
二、淘汰策略
根据redis配置文件提示,8种淘汰策略,大致可分为4种,RUL、RFL、TTL、Randmo
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
#
# LRU means Least Recently Used
# LFU means Least Frequently Used
#
# Both LRU, LFU and volatile-ttl are implemented using approximated
# randomized algorithms.
#
# Note: with any of the above policies, Redis will return an error on write
# operations, when there are no suitable keys for eviction.
#
# At the date of writing these commands are: set setnx setex append
# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
# getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction
LFU && LRU
LFU(Least Frequently Used ,最不经常使用淘汰算法)
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高
TTL淘汰
Redis 数据集数据结构中保存了键值对过期时间的表,即 redisDb.expires。与 LRU 数据淘汰机制类似,TTL 数据淘汰机制中会先从过期时间的表中随机挑选几个键值对,取出其中 ttl 最大的键值对淘汰。同样,TTL淘汰策略并不是面向所有过期时间的表中最快过期的键值对,而只是随机挑选的几个键值对。
Random淘汰:
在随机淘汰的场景下获取待删除的键值对,随机找hash桶再次hash指定位置的dictEntry即可
(1)volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
(2)volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
(3)volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
(4)volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰。
(5)allkeys-lru:从数据集中挑选最近最少使用的数据淘汰
(6)allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰。
(7)allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
(8) no-enviction(驱逐):禁止驱逐数据,这也是默认策略。意思是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用no-enviction策略可以保证数据不被丢失。