摘要: 社区最新GA版本Redis 4.0推出已近一年,阿里云数据库Redis 4.0版也上线近半年,以前关于Redis 4.0的系列文章从源码实现来分析这些新功能,本文旨在从用户角度出发,让Redis的用户可以快速了解并使用Redis 4.0带来的福利。git
Redis做为时下最火爆的NoSQL数据库以性能强悍、数据结构丰富著称,同时其成长的脚步也从未中止,自诞生伊始已经历屡次蜕变不断推出新功能。github
社区最新GA版本Redis 4.0推出已近一年,阿里云数据库Redis 4.0版也上线近半年,以前关于Redis 4.0的系列文章从源码实现来分析这些新功能,本文旨在从用户角度出发,让Redis的用户可以快速了解并使用Redis 4.0带来的福利。redis
大key删除的问题想必不少用户都遇到过,Redis除string外还支持list、set、hash和sorted set等复杂数据结构,这些数据结构丰富了Redis的用法,可是若是使用不当形成单key体积过大的话就会引发一些问题。算法
举个简单的例子,假如某社交网站有一个大V,有上百万的粉丝,咱们能够用set集合类型的数据结构来存储他的粉丝ID,存储粉丝集合的key叫作funs好了,咱们来看下粉丝数:数据库
127.0.0.1:6379> SCARD funs
数据结构
(integer) 6320505
异步
的确是大V,有600多万的粉丝,可是很不幸的有一天这个大V注销了,这时就要删除他的信息,咱们用DEL命令来删除这个key:函数
能够看到删除这个动做竟然耗时3秒多,也就意味着这3秒内Redis没法执行其余命令,这对于线上业务来说是有伤害的,那么如何避免删除大key时的阻塞问题呢?Redis 4.0推出了Lazyfree这一功能,使用UNLINK命令来删除大key,主线程只负责把key从数据库中"摘除",真正的释放动做放在了BIO后台线程去作,咱们来看下效果:性能
能够看到UNLINK执行很快没有产生slowlog。优化
Lazyfree一共有3个命令:
以及4个配置项:
对于源码实现有兴趣的读者能够阅读《Redis 4.0之Lazyfree》。
Redis内嵌了Lua环境来支持用户扩展功能,可是出于数据一致性考虑,要求脚本必须是纯函数的形式,也就是说对于一段Lua脚本给定相同的参数,重复执行其结果都是相同的。
为何要有这个限制呢?缘由是Redis不只仅是单机版的内存数据库,它还支持主从复制和持久化,执行过的Lua脚本会复制给slave以及持久化到磁盘,若是重复执行获得结果不一样,那么就会出现内存、磁盘、slave之间的数据不一致,在failover或者重启以后形成数据错乱影响业务。
仍是以具体例子来看,假设有这么一段Lua脚本,目的很简单就是想记录下当前时间:
这里使用了Redis的TIME命令来获取时间戳,而后存储到名为now的key中,可是其执行时会报错:
错误提示也很明显,若是执行过非肯定性命令(也就是TIME,由于时间是随机的),Redis就不容许执行写命令,以此来保证数据一致性。那如何才能实现随机写入呢?刚才的错误提示也给出了答案,使用redis.replicate_commands(),在执行redis.replicate_commands()以后,Redis就再也不是把整个Lua脚本同步给slave和持久化,而是把脚本中调用Redis的写命令直接去作复制,那么slave和持久化也能够获得肯定的结果。
脚本修改以下:
再执行就能够实现随机写入了:
LFU是Redis 4.0新增的一类内存逐出策略,提供了更精确的内存淘汰算法,其本质是记录了一段时间内key的访问频率,同时也带来了额外的福利就是热点key的发现。
LFU简单来说就是用0-255来表示key的访问频率,值越大说明访问频率越高,而且这里对频率的计数采用的是基于对数的几率增加,LFU为255能够表明100W次的访问,关于LFU的实现有兴趣的读者能够参考《Redis 4.0之基于LFU的热点key发现机制》。
使用OBJECT FREQ命令便可获取指定key的访问频率,不过须要首先把内存逐出策略设置为allkeys-lfu或者volatile-lfu:
使用scan命令遍历全部key,再经过OBJECT FREQ获取访问频率并排序,便可获得热点key。为了方便用户使用,Redis自带的客户端redis-cli也提供了热点key发现功能,执行redis-cli时加上--hotkeys选项便可,示例以下:
分析内存能够优化Redis的使用方式,全新的MEMORY命令能够帮助用户来实现这一操做。
MEMORY命令一共有5个子命令,能够经过MEMORY HELP来查看:
关于各个子命令的详细使用方式能够参考《Redis 4.0之MEMORY命令详解》。