美文网首页
redis6新特性及应用场景介绍

redis6新特性及应用场景介绍

作者: hhwwxxx | 来源:发表于2020-09-08 13:02 被阅读0次

    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文件加载速度优化等因为篇幅时间有限,就没有过多描述了

    谢谢阅读!

    相关文章

      网友评论

          本文标题:redis6新特性及应用场景介绍

          本文链接:https://www.haomeiwen.com/subject/ynukektx.html