redis6新特性及应用场景介绍

redis6刚退出不久,但依然有很多突破性的特性,及早了解新特性和变化,可以在分析业务场景需求时,多一个参考的选择维度

本文将着重从redis6的几个主要特性进行介绍

ps:redis6/redis-cluster-proxy因为使用了c标准库中的并发函数,需要gcc版本4.9以上才可以正常编译

先说结论
1.新增的acl可以有效的对redis集群进行 "分库","权限管理",实现不同业务的区隔
2.resp3使得请求和返回结果,尤其是返回结果,自带类型/size/值的字符长度,使得返回数据可以脱离redis系统的限制,提供更丰富精准的数据定义,实现比json更高效的解析
3.新推出的客户端缓存,有比较丰富的实现,对较复杂/数据量较大的 热读/冷写 有比较大的性能提升
4.官方推出的集群模块,可以有效地将底层redis集群抽象化,无需额外计算solt落点,批量操作透明化,并可以与acl相结合,实现不同proxy节点,不同默认用户 and 单独指定认证用户,使用专有链接等功能,缺点是,目前看来与resp3的结合不是很紧密,无法使用hello切换resp协议,且不支持客户端缓存

1.新增ACL的支持

因为redis的定位:内网高性能内存数据库
所以一直以来redis都只有最简单的auth和bind两种权限控制的方式,其他的安全都交给了网关和操作系统
但auth的权限控制粒度很粗糙,只能 给用户设置密码 or 不设置密码,网络连接更是明文交互

这次,redis6推出了两个强大的安全功能,ACL和SSL支持
SSL的支持,使得服务器间,服务器和客户端之间的网络,即使是不安全的,也能保证数据安全的传输,这里不做多的说明
ACL的出现,使得可以给每个用户设置单独的密码和操作权限,这些权限分为2类:
1.允许/禁止用户执行的命令(集)
2.用户有权限的key(正则匹配)

通过这两类的权限组合,可以将某个用户的操作权限,操作key控制在某个范围,再结合key的命令规范
1.比如某一业务key全部以 "XXXX:" 作为开头,通过将业务下账号的权限控制在 "XXXX:", 限定业务下账号可能影响的范围(即使最严重的后果,也就是丢失全部 "XXXX:" 的数据)
2.业务下不同账号,通过控制他们能执行的命令范围,区分出不同的账号权限(只有 get类命令的读账号,以及有 set类写权限的写账号)
3.通过禁止业务下账号执行flushall,flushdb等高危操作,避免了"业务需要用","用的多了,难免出问题"的死循环
4.可以通过从配置文件导入或者从指定的权限控制文件导入(两种方式等价,只能二选一)导入用户权限,可以快速批量的实现权限的群组控制

具体示例如下:

192.168.23.87:6519> acl setuser sre #创建新的用户sre
OK
192.168.23.87:6519> acl list #查看用户列表
1) "user default on nopass ~* +@all"
2) "user sre off -@all"
192.168.23.87:6519> ACL SETUSER sre >sre_pass ~workflow:* +get
# 给sre用户收授权
# >sre_pass 表示设置sre的密码为sre_pass
# ~workflow:* 是授权给sre对"workflow:" 开头的key的操作权限
# +get 是给sre用户执行get操作的权限
OK
192.168.23.87:6519> ACL GETUSER sre #获取sre用户的权限详情
1# "flags" => 1~ "off"
2# "passwords" => 1) "a86284e57caea7be53718afbd4518db9da7676b83171575cc177d563b13a5549"
3# "commands" => "-@all +get"
4# "keys" => 1) "workflow:"
192.168.23.87:6519> acl list
1) "user default on nopass ~
+@all"
2) "user sre off #a86284e57caea7be53718afbd4518db9da7676b83171575cc177d563b13a5549 ~workflow:* -@all +get"
192.168.23.87:6519> ACL SETUSER sre +set # 给sre用户追加 set 操作的权限
OK
192.168.23.87:6519> ACL SETUSER sre ~cmdb:* 给sre用户追加操作 cmdb: 开头key的权限
OK
192.168.23.87:6519> ACL GETUSER sre
1# "flags" => 1~ "off"
2# "passwords" => 1) "a86284e57caea7be53718afbd4518db9da7676b83171575cc177d563b13a5549"
3# "commands" => "-@all +set +get"
4# "keys" => 1) "workflow:"
2) "cmdb:
"
192.168.23.87:6519> ACL SETUSER sre on #激活sre用户 (非激活不可登陆)
OK
192.168.23.87:6519> acl list
1) "user default on nopass ~* +@all"
2) "user sre on #a86284e57caea7be53718afbd4518db9da7676b83171575cc177d563b13a5549 ~workflow:* ~cmdb:* -@all +set +get"
192.168.23.87:6519> config get acl # 查看acl相关配置
1# "aclfile" => "/opt/gredis-6.0.6/conf/redis-master-6519.aclfile" # aclfile文件位置(没有单独aclfile则为空字符串)
2# "acllog-max-len" => "128" # acl 日志的最大长度
192.168.23.87:6519>
192.168.23.87:6519> auth sre sre_pass # 登陆sre用户
OK
192.168.23.87:6519> set cmdb:k1 cmdbv1
OK
192.168.23.87:6519> get cmdb:k1
"cmdbv1"
192.168.23.87:6519> hset cmdbnk1 ccc ddd # 提示没有hset操作的权限
(error) NOPERM this user has no permissions to run the 'hset' command or its subcommand
192.168.23.87:6519> set sre_workflow:k1 v1 #提示没有操作 sre_workflow: 开头key的权限
(error) NOPERM this user has no permissions to access one of the keys used as arguments
192.168.23.87:6519> set sre:k1 v1 #提示没有操作 sre: 开头key的权限
(error) NOPERM this user has no permissions to access one of the keys used as arguments
[root@host-192-168-23-87 ~]# cat /opt/gredis-6.0.6/conf/redis-master-6519.aclfile # 查看aclfile配置
user default on #37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688f ~* +@all
user sre on #a86284e57caea7be53718afbd4518db9da7676b83171575cc177d563b13a5549 ~workflow:* ~cmdb:* -@all +set +get
192.168.23.87:6519> ACL SETUSER aclfile_user # 新增aclfile_user 用户
OK
[root@host-192-168-23-87 ~]# cat /opt/gredis-6.0.6/conf/redis-master-6519.aclfile # 查看aclfile配置
user aclfile_user off -@all
user default on #37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688f ~* +@all
user sre on #a86284e57caea7be53718afbd4518db9da7676b83171575cc177d563b13a5549 ~workflow:* ~cmdb:* -@all +set +get

2.resp3通信协议

为了支持更多的新特性,以及将通信协议"语义化"的目的,对原有的resp协议进行了升级,主要新增特点:
1.新增了多种新的数据类型,支持更丰富的数据格式
2.新增的数据类型,以及原有的数据类型,每一种都有一个自己独有的"首字符",结合数据类型的"大小值",可以实现数据的层层嵌套,快速解析,而且使得数据脱离了具体的命令,即,只要拿到对应的"请求/返回"数据,就可以还原出具体的"请求/返回"的数据格式
3.新增了未知长度的"流"模式的数据类型

原有类型和新增类型之间关系
resp3与resp2等价的类型
Array: 一个有序集合,包含N个其它类型
Blob string: 二进制安全字符串
Simple string: 一个节省空间的非二进制安全字符串
Simple error: 一个节省空间的非二进制安全错误码和错误信息
Number: 有符号64位整数

resp3新增的类型
Null: 单一的空值,代替原先的 RESP v2 的*-1 和 $-1 空值。
Double: 浮点数
Boolean: 布尔类型 true / false
Blob error: 二进制安全的错误码和错误信息
Verbatim string: 一个二进制安全字符串,带文本格式, 如命令LATENCY DOCTOR的输出
Map: 一个有序的键值对
Set: 一个无序的不重复的集合
Attribute: 类似Map类型
Push: 带外数据,格式类似数组,但是客户端需要检查第一个数据,第一个数据指示了带外数据的类型。注意带外数据并不是一个reply,它是redis主动推送的数据,所以客户端收到带外数据,交给对应的处理方法去处理后,你还需要继续读取你的reply数据
Hello: hello命令的返回结果,类似Map类型,仅仅在客户端和服务器建立连接的时候发送
Big number: 大数字类型
还有一种新加的stream类型,可以用来传送不确定具体长度的数据。在数据的开头有固定的标识符,在数据传输完毕后在加上这个40字节的标识符,40字节的标志符基本上不会和传输的数据有重复

resp3协议中,有几类数据的"首字母"也做了更细粒度的区分,具体如下

数据类型 resp2 resp3
Simple error + -
Verbatim string $ =
map * %
set * ~
Attribute * |
Push * >
Streamed strings $(字符长度)<CR><LF>(指定长度字符)<CR><LF> $?<CR><LF>(任意发送次数,每次发送任意长度,每次发送遵循对应数据格式规范);0<CR><LF>(;0<CR><LF>作为固定的传输结束标识)
Streamed aggregated data *(items数量)<CR><LF>(只能有指定数量的items,items之间<CR><LF>分隔) *?<CR><LF>[任意数量items].<CR><LF>

可以看出resp2到reps3,支持了更灵活,更精确的类型语义,在数据传输,解析上,有更大的灵活性和效率

redis6可以通过hello 2(默认协议) , hello 3 切换resp协议的版本,会根据新的协议格式返回相关信息,具体如下

192.168.23.87:6519> hello 3
1# "server" => "redis"
2# "version" => "6.0.6"
3# "proto" => (integer) 3
4# "id" => (integer) 4
5# "mode" => "standalone"
6# "role" => "master"
7# "modules" => (empty array)

hello3抓包
hello 3
%7
$6
server
$5
redis
$7
version
$5
6.0.6
$5
proto
:3
$2
id
:5
$4
mode
$10
standalone
$4
role
$6
master
$7
modules
*0

192.168.23.87:6519> hello 2
1) "server"
2) "redis"
3) "version"
4) "6.0.6"
5) "proto"
6) (integer) 2
7) "id"
8) (integer) 4
9) "mode"
10) "standalone"
11) "role"
12) "master"
13) "modules"
14) (empty array)

hello2抓包
*14
$6
server
$5
redis
$7
version
$5
6.0.6
$5
proto
:2
$2
id
:5
$4
mode
$10
standalone
$4
role
$6
master
$7
modules
*0

通过hello2 和hello3 的抓包返回数据,可以发现,返回的第一列数据,已经从 *14 变为了 %7
即从 kv各占一行的list 变为了 size=7的map, 从语义的清晰和数据的容错上都有更好的表现
其他类似的类型"首字符"的转变就不再演示

3.redis客户端缓存

客户端缓存是redis6推出的一个比较重要的功能,正式发版前后,还有过比较大的调整修改
客户端缓存的目的是减少通过网络读取redis库的数量,将 tcp获取数据 -> 本地内存获取数据 ,以此获得数量级的提升
客户端缓存最适合的场景是 多读少写, 比如热帖,热评等,阅读量和回复/修改量有很大(数量级)差别,直接从内存读写的话,可以在不升级服务器配置的情况下,将相应请求响应支持数再提升一个数量级
ps:目前redis-cluster-proxy模块不支持客户端缓存设置
客户端缓存只有在resp3的协议下才能最好的实现(resp2只能曲线实现,这里就不多描述了)

客户端缓存有两种模式

默认模式:服务器记录客户端(id)访问了哪些key,当其中的key发生变更时给客户端发送失效信息,消耗服务器端内存

广播模式:客户端订阅访问过的key的前缀,当符合模式的key发生变更就会被通知(即使变更的key没有被客户端缓存),服务器端不记录客户端访问的key,因此不会消耗服务器端的内存;

两者适用于不同的场景

1.默认模式消耗的是服务的资源(记录key-客户端id的时效映射表),广播模式消耗的是网络带宽 + 客户端资源(即使没有缓存,只要是订阅的key前缀被修改,都会收到通知)
2.当订阅客户端较多,且和key前缀有强关联(业务相关)时,适合广播模式,因为服务器可以对每一个key前缀做一次加工,然后将加工后的数据按订阅客户端id重复群发,如果是默认模式的话,只能挨个发送

可以通过 client tracking on 或者 client tracking off 来开启关闭客户端缓存模式
开启的缓存模式有

CLIENT TRACKING on REDIRECT 8 BCAST {0,}[prefix 匹配前缀] //订阅匹配前缀的失效消息(不指定前缀则订阅全部key的失效消息)
CLIENT TRACKING on REDIRECT 8 [optin | optout]
CLIENT CACHING yes
当使用optin选项时,只有执行 CLIENT CACHING yes 后的第一个get才会被订阅/缓存
如果是事务/Lua脚本中执行 CLIENT CACHING yes , 则会订阅/缓存全部涉及的key

需要注意的是,两种模式的切换,需要通过 CLIENT TRACKING off 来切换

代码示例

192.168.23.87:6519> CLIENT TRACKING on REDIRECT 8
OK
192.168.23.87:6519> CLIENT TRACKING on REDIRECT 7
(error) ERR The client ID you want redirect to does not exist
192.168.23.87:6519> CLIENT TRACKING on bcast
(error) ERR You can't switch BCAST mode on/off before disabling tracking for this client, and then re-enabling it with a different mode.
192.168.23.87:6519> CLIENT TRACKING off
OK
192.168.23.87:6519> CLIENT TRACKING on REDIRECT 8 BCAST prefix k
OK

4.redis代理模块redis-cluster-proxy

为了更方便的管理redis集群,简化客户端的操作,redis6推出了官方的代理模块redis-cluster-proxy
redis-cluster-proxy的启动很简单

git clone https://github.com/artix75/redis-cluster-proxy
cd redis-cluster-proxy
make install
redis-cluster-proxy {1,}[ cluster-master:port] -p 7777(不设置的默认端口)

简单4个命令就启动了对一个集群的proxy

链接proxy的方式与client链接server一致,指定ip,port即可链接

redis-cli -h 192.168.23.87 -p 7777

如果需要个proxy设置一个默认用户(权限),可以在启动时时添加参数

redis-cluster-proxy --auth-user default --auth default 192.168.23.87:7777

除此之外,还可以设置连接池最大/最小/默认值,填充的间隔和时间等参数

ps:需要注意的是,链接proxy的客户端可以是redis6以前的版本,但之前的版本会使用resp2的协议,以proxy info命令执行的结果区别展示如下

redis5-cli链接proxy执行 proxy info 命令
redis6-cli链接proxy执行 proxy info 命令

proxy info命令展示的信息有:
多路复用的api:epoll
端口:7777
proxy已经运行的秒/时间
使用内存/系统内存
连接proxy的client数/共享连接池连接数/每个连接使用数
活跃连接cluster的ip:port列表

可以通过proxy help 查看帮助


proxy help

proxy info 可以查看cluster的master节点信息(ip,port,solt数量,分片数量,连接数),与proxy cluster info一致
proxy config get 配置key 可以查看proxy的相关配置的值
proxy config get 配置key 设置value 可以设置proxy的先关值

其中几个比较重要的参数
PROXY CONFIG SET enable-cross-slot 1 开启跨solt查询(默认关闭)
PROXY MULTIPLEXING STATUS | OFF 查询多路复用的状态,或者关闭多路复用(使用专有链接)
PROXY CONFIG SET log-level debug 设置日志级别为debug(debug,info,success,warning,error(默认为debug))

PROXY COMMAND [UNSUPPORTED|CROSSSLOTS-UNSUPPORTED] 查看[所有proxy | proxy跨solt查询]不支持的命令

以上是redis6主要特性以及使用场景的大致介绍,其他像"并发进行socket读写",消息队列模块,无磁盘数据同步,rdb文件加载速度优化等因为篇幅时间有限,就没有过多描述了

谢谢阅读!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345