Redis 6 新功能提前看!

本文内容主要基于 Salvatore Sanfilippo 在今年六月26-27日 Redis Day New York 上关于 Redis 6 新功能的分享,加上目前在官方(博客、Twitter等)已经公开内容作为补充,并通过 Github 上的 unstable 分支(截至本文时间2019年8月2日)进行测试验证。

Overview

Salvatore Sanfilippo(以下均简称为作者)在 Redis Day New York 上的分享在YouTube 上已经发布,原链接请见链接(当然,你需要科学的上网工具)。
啥也不说,先上原图。

Redis 6 新功能提前看!

嗯,相当魔性。这个就是作者分享的原图。别人都是带个精心准备好的PPT,他就带个白板上来画画画,有技术就可以为所欲为?>_<

作者先简单介绍 Redis 6 会给大家提供的新功能,包括:

一、对用户使用有直接影响的功能

  1. ACL用户权限控制功能
  2. RESP3:新的 Redis 通信协议
  3. Cluster 管理工具
  4. SSL 支持

二、Redis 内部的优化

  1. IO多线程支持
  2. 新的Module API
  3. 新的 Expire 算法

三、外部工具

  1. Redis Cluster Proxy
  2. Disque

作者分享着重介绍了(一)里面的1-3点,其他几点有所提及。本文也按照这个内容进行分享。

ACL

目前的 Redis(5及以下版本),没有用户权限管理这个概念,只有一个AUTH密码验证功能,基本上能够接入的用户就是root用户。
ACL 就是为了避免接入的用户进行危险命令的操作开发的功能,这类命令如 FLUSHALLDEBUG等。还记得我之前分享过的一篇文章《从清档到二级索引》
多年来 Redis 管理员通过RENAME命令来进行限制。另一方面,开发人员有时候不清楚一些Redis 驱动的内部实现,可能无意中触发一些危险命令,所以也需要进行限制。
Redis 6 中加入ACL的功能,能够对接入的用户进行三个层面的权限控制:
(1)接入权限:用户名和密码;
(2)可以执行的命令;
(3)可以操作的 KEY。
下面我们实际代码中看看效果,下面展示我创建一个用户aaron,设置他的密码,允许执行所有命令,针对所有KEY。

127.0.0.1:6380> ACL WHOAMI
"default"
127.0.0.1:6380> ACL setuser aaron on >mypasswd +@all ~*
OK
127.0.0.1:6380> AUTH aaron mypasswd
OK
127.0.0.1:6380> ACL WHOAMI
"aaron"
127.0.0.1:6380> GET foo
(nil)
127.0.0.1:6380> SET foo bar
OK

然后我尝试将 aaron 这个用户去掉SET命令的权限。

127.0.0.1:6380> ACL setuser aaron -SET
OK
127.0.0.1:6380> SET foo 123
(error) NOPERM this user has no permissions to run the 'set' command or its subcommand

我们也可以控制用户可以对哪些 KEY 进行操作,比如下面演示一个叫做 Ben 的用户,他只能创建以 ben 为前缀的 KEY。

127.0.0.1:6380> ACL setuser ben on >mypasswd +@all ~ben*
OK
127.0.0.1:6380> set foo bar
(error) NOPERM this user has no permissions to access one of the keys used as arguments
127.0.0.1:6380> set benfoo bar
OK

"default" 用户是我们默认连接入 Redis 时的用户,默认情况下这个用户有所有的权限,当然了,我们也可以像以前那样给默认用户设置权限。通过ACL list可以查看当前有哪些用户和他们的权限和密码(前提是该用户有ACL命令的权限)。

127.0.0.1:6380> ACL list
1) "user aaron on >mypasswd ~* +@all -set"
2) "user default on nopass ~* +@all"

作者提到ACL功能是基于 bitmap 实现的,对性能几乎没有影响。
关于ACL功能就介绍到这里,有兴趣的作者可以看官方文档:
https://redis.io/topics/acl

RESP3

RESP 全称 REdis Serialization Protocol,是 Redis 服务端与客户端之间通信的协议。Redis 5 使用的是 RESP2,而 Redis 6 开始在兼容 RESP2 的基础上,开始支持 RESP3。其实一开始作者是打算完全放弃 RESP2的,后来被劝退了。详情见链接(http://antirez.com/news/125)。
那么 RESP3 有哪些改进的地方呢?
照例上个原图:

Redis 6 新功能提前看!

这个图中,作者分享的是,在 RESP2 中,所有的返回内容,都是一个字符串数组的形式,不管是 list 还是 sorted set。因此客户端需要自行去根据类型进行解读,增加了客户端实现的复杂性。
下面以具体的命令展示 RESP3 中的具体变化。

127.0.0.1:6380> HSET myhash a 1 b 2 c 3
(integer) 3
127.0.0.1:6380> HGETALL myhash
1) "a"
2) "1"
3) "b"
4) "2"
5) "c"
6) "3"
127.0.0.1:6380> HELLO 3 #转换成RESP3的命令
1# "server" => "redis"
2# "version" => "999.999.999"
3# "proto" => (integer) 3
4# "id" => (integer) 5
5# "mode" => "standalone"
6# "role" => "master"
7# "modules" => (empty array)
127.0.0.1:6380> HGETALL myhash
1# "a" => "1"
2# "b" => "2"
3# "c" => "3"

其实从 redis-cli 来看意义不大,因为显示出来的信息已经经过处理,最直接的方式是直接telnet之后进行操作看返回结果:

$ telnet 127.0.0.1 6380
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
AUTH aaron mypasswd
+OK
HGETALL myhash
*4
$1
a
$1
1
$1
b
$1
2
HELLO 3
(此处省略)
HGETALL myhash
%2
$1
a
$1
1
$1
b
$1
2

可以看到,以前返回两个field的hash,就是直接无差别地返回4个值,而新的RESP3就会告诉客户端返回两个key-value,通过%表示键值对(也成为map类型)的个数。
另外作者也对空字符串进行了定义:

(RESP2)
GET null_key
$-1
(RESP3)
GET null_key
_

其他新的定义还有不少,比如支持 Boolean 类型,set集合类型等等,有兴趣的读者,也是可以去详细看看 RESP3 的设计稿:
https://github.com/antirez/RE...

除了具体的数据类型,RESP3 开始支持KEY属性类型(Attribute type),使服务器和客户端之间可以实现更复杂的功能,比如返回信息里带上一个Key的访问频率,使客户端能实现更智能的缓存功能(http://antirez.com/news/130)。话说,客户端缓存功能,可以说是在提升 Redis 作为缓存的读写能力有了质的飞跃,值得期待。

其他

其他方面作者没有作太深入的分享,因此我下面也只是简单提一下,并且附上相关的资料,如果读者有兴趣想了解,欢迎留言给我,我下次分享相关主题。

Cluster 管理工具

作者分享说redis-trib.rb的功能集成到redis-cli,但这个不是 Redis 5 就已经做了的事情吗?看了一圈,也并没有太大的变化,就增加了一个backup命令。

除了redis-cli,其实另一个工具的优化更让人喜闻乐见,就是redis-benchmark

$ src/redis-benchmark --help
Usage: redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests>] [-k <boolean>]
(省略部分输出结果……)
 --threads <num>    Enable multi-thread mode.
 --cluster          Enable cluster mode.
 --enable-tracking  Send CLIENT TRACKING on before starting benchmark.

官方benchmark工具总算支持cluster了,通过多线程的方式对多个分片进行压测。

支持 SSL 连接

Amazon 提供的一个功能,在 Redis 6 中 merge 进来。没有提及细节,不清楚对性能有多大影响。

IO多线程

Redis 终于实现多线程了!?先打住,多线程是不可能多线程的,这辈子都不可能多线程(后面这句是我加的)。

作者先简单解释了为什么不能多线程(复杂性、锁的效率等等),然后提到就是有一个事情可以做成多线程,就是针对客户端的这部分。这个操作通过系统调用写操作,将客户端的输入输出缓冲中的数据通过多线程IO与客户端交互。作者说这部分通常能够占到CPU负载的50%,将这部分通过其他线程进行处理,核心流程还是单线程,实现起来也比较简单,性价比超高,所以就做了。
这样能进一步提升单实例的性能,使用4核、8核等来分散写压力,不过再多几个核估计收益比不高了。如果真正想发挥多核性能,还是老路子——Cluster。

Modules API

新的Modules API,让Module功能可以做更多的事情,但作者没有展开讲。

新Expire过期算法

这部分因为涉及到的背景和算法比较多,所以会另外开一个 session 来分享。(视频也可以在YouTube上看了)

Proxy

针对 Cluster 的代理,这么多年了,仍然有不少人在Cluster的接入方式上挣扎,因为缺少合适的驱动而无法使用Cluster。所以开发了这个Proxy功能。作者也强调,虽然这个Proxy 让 Cluster 拥有了像单实例一样的接入方式,但是本质上还是 Cluster,不支持的命令还是不会支持,比如跨 slot 的多Key操作。
其实社区早已有过不少 Proxy 方面的尝试,而且有些做的还不错。那么这个官方的 Proxy 究竟会给我们带来什么惊喜呢?还是让我们拭目以待吧。

Disque

这个本来是作者几年前开发的一个基于 Redis 的消息队列工具,但多年来作者发现 Redis 在持续开发时,他也要持续把新的功能合并到这个Disque 项目里面,这里有大量无用的工作。因此这次他在 Redis 的基础上通过 Modules 功能实现 Disque。

如果业务并不需要保持严格消息的顺序,这个 Disque 能提供足够简单和快速的消息队列功能。

总结

对我来说,这个版本可以说有史以来变化最大的一次升级(如果不是最大也是之一了)。不管是从使用者,DBA,客户端工具开发者,还是运维的角度来看,都有了不少的变化。这次升级使得 Redis 从整体上更接近一个完整的数据库(对比 MongoDB)。另一方面,这次升级给所有相关的人员带来了很多变化,恐怕后面要忙好一阵子了。

不知道大家看完 Redis 6 的新功能之后有什么感想?限于篇幅,本文只是按作者重点分享的内容进行整理,其实每一项变化似乎都可以新写一篇文章来分享。如果有你感兴趣的内容,也可以留言一下,有机会下次我可以分享。


更多资讯,欢迎关注公众号:最简实践
Redis 6 新功能提前看!

相关推荐