redis6剛退出不久,但依然有很多突破性的特性,及早了解新特性和變化,可以在分析業(yè)務(wù)場景需求時,多一個參考的選擇維度
本文將著重從redis6的幾個主要特性進行介紹
ps:redis6/redis-cluster-proxy因為使用了c標準庫中的并發(fā)函數(shù),需要gcc版本4.9以上才可以正常編譯
先說結(jié)論
1.新增的acl可以有效的對redis集群進行 "分庫","權(quán)限管理",實現(xiàn)不同業(yè)務(wù)的區(qū)隔
2.resp3使得請求和返回結(jié)果,尤其是返回結(jié)果,自帶類型/size/值的字符長度,使得返回數(shù)據(jù)可以脫離redis系統(tǒng)的限制,提供更豐富精準的數(shù)據(jù)定義,實現(xiàn)比json更高效的解析
3.新推出的客戶端緩存,有比較豐富的實現(xiàn),對較復雜/數(shù)據(jù)量較大的 熱讀/冷寫 有比較大的性能提升
4.官方推出的集群模塊,可以有效地將底層redis集群抽象化,無需額外計算solt落點,批量操作透明化,并可以與acl相結(jié)合,實現(xiàn)不同proxy節(jié)點,不同默認用戶 and 單獨指定認證用戶,使用專有鏈接等功能,缺點是,目前看來與resp3的結(jié)合不是很緊密,無法使用hello切換resp協(xié)議,且不支持客戶端緩存
1.新增ACL的支持
因為redis的定位:內(nèi)網(wǎng)高性能內(nèi)存數(shù)據(jù)庫
所以一直以來redis都只有最簡單的auth和bind兩種權(quán)限控制的方式,其他的安全都交給了網(wǎng)關(guān)和操作系統(tǒng)
但auth的權(quán)限控制粒度很粗糙,只能 給用戶設(shè)置密碼 or 不設(shè)置密碼,網(wǎng)絡(luò)連接更是明文交互
這次,redis6推出了兩個強大的安全功能,ACL和SSL支持
SSL的支持,使得服務(wù)器間,服務(wù)器和客戶端之間的網(wǎng)絡(luò),即使是不安全的,也能保證數(shù)據(jù)安全的傳輸,這里不做多的說明
ACL的出現(xiàn),使得可以給每個用戶設(shè)置單獨的密碼和操作權(quán)限,這些權(quán)限分為2類:
1.允許/禁止用戶執(zhí)行的命令(集)
2.用戶有權(quán)限的key(正則匹配)
通過這兩類的權(quán)限組合,可以將某個用戶的操作權(quán)限,操作key控制在某個范圍,再結(jié)合key的命令規(guī)范
1.比如某一業(yè)務(wù)key全部以 "XXXX:" 作為開頭,通過將業(yè)務(wù)下賬號的權(quán)限控制在 "XXXX:", 限定業(yè)務(wù)下賬號可能影響的范圍(即使最嚴重的后果,也就是丟失全部 "XXXX:" 的數(shù)據(jù))
2.業(yè)務(wù)下不同賬號,通過控制他們能執(zhí)行的命令范圍,區(qū)分出不同的賬號權(quán)限(只有 get類命令的讀賬號,以及有 set類寫權(quán)限的寫賬號)
3.通過禁止業(yè)務(wù)下賬號執(zhí)行flushall,flushdb等高危操作,避免了"業(yè)務(wù)需要用","用的多了,難免出問題"的死循環(huán)
4.可以通過從配置文件導入或者從指定的權(quán)限控制文件導入(兩種方式等價,只能二選一)導入用戶權(quán)限,可以快速批量的實現(xiàn)權(quán)限的群組控制
具體示例如下:
192.168.23.87:6519> acl setuser sre
#創(chuàng)建新的用戶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用戶收授權(quán)
# >sre_pass 表示設(shè)置sre的密碼為sre_pass
# ~workflow:* 是授權(quán)給sre對"workflow:" 開頭的key的操作權(quán)限
# +get 是給sre用戶執(zhí)行g(shù)et操作的權(quán)限
OK
192.168.23.87:6519> ACL GETUSER sre#獲取sre用戶的權(quán)限詳情
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 操作的權(quán)限
OK
192.168.23.87:6519> ACL SETUSER sre ~cmdb:*給sre用戶追加操作 cmdb: 開頭key的權(quán)限
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相關(guān)配置
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操作的權(quán)限
(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的權(quán)限
(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的權(quán)限
(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通信協(xié)議
為了支持更多的新特性,以及將通信協(xié)議"語義化"的目的,對原有的resp協(xié)議進行了升級,主要新增特點:
1.新增了多種新的數(shù)據(jù)類型,支持更豐富的數(shù)據(jù)格式
2.新增的數(shù)據(jù)類型,以及原有的數(shù)據(jù)類型,每一種都有一個自己獨有的"首字符",結(jié)合數(shù)據(jù)類型的"大小值",可以實現(xiàn)數(shù)據(jù)的層層嵌套,快速解析,而且使得數(shù)據(jù)脫離了具體的命令,即,只要拿到對應(yīng)的"請求/返回"數(shù)據(jù),就可以還原出具體的"請求/返回"的數(shù)據(jù)格式
3.新增了未知長度的"流"模式的數(shù)據(jù)類型
原有類型和新增類型之間關(guān)系
resp3與resp2等價的類型
Array: 一個有序集合,包含N個其它類型
Blob string: 二進制安全字符串
Simple string: 一個節(jié)省空間的非二進制安全字符串
Simple error: 一個節(jié)省空間的非二進制安全錯誤碼和錯誤信息
Number: 有符號64位整數(shù)
resp3新增的類型
Null: 單一的空值牛曹,代替原先的 RESP v2 的*-1 和 $-1 空值帆疟。
Double: 浮點數(shù)
Boolean: 布爾類型 true / false
Blob error: 二進制安全的錯誤碼和錯誤信息
Verbatim string: 一個二進制安全字符串,帶文本格式禁舷, 如命令LATENCY DOCTOR的輸出
Map: 一個有序的鍵值對
Set: 一個無序的不重復的集合
Attribute: 類似Map類型
Push: 帶外數(shù)據(jù)耕魄,格式類似數(shù)組,但是客戶端需要檢查第一個數(shù)據(jù)睁本,第一個數(shù)據(jù)指示了帶外數(shù)據(jù)的類型艳吠。注意帶外數(shù)據(jù)并不是一個reply工育,它是redis主動推送的數(shù)據(jù),所以客戶端收到帶外數(shù)據(jù)鹃愤,交給對應(yīng)的處理方法去處理后簇搅,你還需要繼續(xù)讀取你的reply數(shù)據(jù)
Hello: hello命令的返回結(jié)果,類似Map類型,僅僅在客戶端和服務(wù)器建立連接的時候發(fā)送
Big number: 大數(shù)字類型
還有一種新加的stream類型昼浦,可以用來傳送不確定具體長度的數(shù)據(jù)馍资。在數(shù)據(jù)的開頭有固定的標識符,在數(shù)據(jù)傳輸完畢后在加上這個40字節(jié)的標識符关噪,40字節(jié)的標志符基本上不會和傳輸?shù)臄?shù)據(jù)有重復
resp3協(xié)議中,有幾類數(shù)據(jù)的"首字母"也做了更細粒度的區(qū)分,具體如下
數(shù)據(jù)類型 | resp2 | resp3 |
---|---|---|
Simple error | + | - |
Verbatim string | $ | = |
map | * | % |
set | * | ~ |
Attribute | * | | |
Push | * | > |
Streamed strings | $(字符長度)<CR><LF>(指定長度字符)<CR><LF> | $?<CR><LF>(任意發(fā)送次數(shù),每次發(fā)送任意長度,每次發(fā)送遵循對應(yīng)數(shù)據(jù)格式規(guī)范);0<CR><LF>(;0<CR><LF>作為固定的傳輸結(jié)束標識) |
Streamed aggregated data | *(items數(shù)量)<CR><LF>(只能有指定數(shù)量的items,items之間<CR><LF>分隔) | *?<CR><LF>[任意數(shù)量items].<CR><LF> |
可以看出resp2到reps3,支持了更靈活,更精確的類型語義,在數(shù)據(jù)傳輸,解析上,有更大的靈活性和效率
redis6可以通過hello 2(默認協(xié)議) , hello 3 切換resp協(xié)議的版本,會根據(jù)新的協(xié)議格式返回相關(guān)信息,具體如下
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 的抓包返回數(shù)據(jù),可以發(fā)現(xiàn),返回的第一列數(shù)據(jù),已經(jīng)從 *14 變?yōu)榱?%7
即從 kv各占一行的list 變?yōu)榱?size=7的map, 從語義的清晰和數(shù)據(jù)的容錯上都有更好的表現(xiàn)
其他類似的類型"首字符"的轉(zhuǎn)變就不再演示
3.redis客戶端緩存
客戶端緩存是redis6推出的一個比較重要的功能,正式發(fā)版前后,還有過比較大的調(diào)整修改
客戶端緩存的目的是減少通過網(wǎng)絡(luò)讀取redis庫的數(shù)量,將 tcp獲取數(shù)據(jù) -> 本地內(nèi)存獲取數(shù)據(jù) ,以此獲得數(shù)量級的提升
客戶端緩存最適合的場景是 多讀少寫, 比如熱帖,熱評等,閱讀量和回復/修改量有很大(數(shù)量級)差別,直接從內(nèi)存讀寫的話,可以在不升級服務(wù)器配置的情況下,將相應(yīng)請求響應(yīng)支持數(shù)再提升一個數(shù)量級
ps:目前redis-cluster-proxy模塊不支持客戶端緩存設(shè)置
客戶端緩存只有在resp3的協(xié)議下才能最好的實現(xiàn)(resp2只能曲線實現(xiàn),這里就不多描述了)
客戶端緩存有兩種模式
默認模式:服務(wù)器記錄客戶端(id)訪問了哪些key鸟蟹,當其中的key發(fā)生變更時給客戶端發(fā)送失效信息,消耗服務(wù)器端內(nèi)存
廣播模式:客戶端訂閱訪問過的key的前綴使兔,當符合模式的key發(fā)生變更就會被通知(即使變更的key沒有被客戶端緩存),服務(wù)器端不記錄客戶端訪問的key建钥,因此不會消耗服務(wù)器端的內(nèi)存;
兩者適用于不同的場景
1.默認模式消耗的是服務(wù)的資源(記錄key-客戶端id的時效映射表),廣播模式消耗的是網(wǎng)絡(luò)帶寬 + 客戶端資源(即使沒有緩存,只要是訂閱的key前綴被修改,都會收到通知)
2.當訂閱客戶端較多,且和key前綴有強關(guān)聯(lián)(業(yè)務(wù)相關(guān))時,適合廣播模式,因為服務(wù)器可以對每一個key前綴做一次加工,然后將加工后的數(shù)據(jù)按訂閱客戶端id重復群發(fā),如果是默認模式的話,只能挨個發(fā)送
可以通過 client tracking on 或者 client tracking off 來開啟關(guān)閉客戶端緩存模式
開啟的緩存模式有
CLIENT TRACKING on REDIRECT 8 BCAST {0,}[prefix 匹配前綴] //訂閱匹配前綴的失效消息(不指定前綴則訂閱全部key的失效消息)
CLIENT TRACKING on REDIRECT 8 [optin | optout]
CLIENT CACHING yes
當使用optin選項時,只有執(zhí)行 CLIENT CACHING yes 后的第一個get才會被訂閱/緩存
如果是事務(wù)/Lua腳本中執(zhí)行 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(不設(shè)置的默認端口)
簡單4個命令就啟動了對一個集群的proxy
鏈接proxy的方式與client鏈接server一致,指定ip,port即可鏈接
redis-cli -h 192.168.23.87 -p 7777
如果需要個proxy設(shè)置一個默認用戶(權(quán)限),可以在啟動時時添加參數(shù)
redis-cluster-proxy --auth-user default --auth default 192.168.23.87:7777
除此之外,還可以設(shè)置連接池最大/最小/默認值,填充的間隔和時間等參數(shù)
ps:需要注意的是,鏈接proxy的客戶端可以是redis6以前的版本,但之前的版本會使用resp2的協(xié)議,以proxy info命令執(zhí)行的結(jié)果區(qū)別展示如下
proxy info命令展示的信息有:
多路復用的api:epoll
端口:7777
proxy已經(jīng)運行的秒/時間
使用內(nèi)存/系統(tǒng)內(nèi)存
連接proxy的client數(shù)/共享連接池連接數(shù)/每個連接使用數(shù)
活躍連接cluster的ip:port列表
可以通過proxy help 查看幫助
proxy info 可以查看cluster的master節(jié)點信息(ip,port,solt數(shù)量,分片數(shù)量,連接數(shù)),與proxy cluster info一致
proxy config get 配置key 可以查看proxy的相關(guān)配置的值
proxy config get 配置key 設(shè)置value 可以設(shè)置proxy的先關(guān)值
其中幾個比較重要的參數(shù)
PROXY CONFIG SET enable-cross-slot 1 開啟跨solt查詢(默認關(guān)閉)
PROXY MULTIPLEXING STATUS | OFF 查詢多路復用的狀態(tài),或者關(guān)閉多路復用(使用專有鏈接)
PROXY CONFIG SET log-level debug 設(shè)置日志級別為debug(debug,info虐沥,success熊经,warning,error(默認為debug))
PROXY COMMAND [UNSUPPORTED|CROSSSLOTS-UNSUPPORTED] 查看[所有proxy | proxy跨solt查詢]不支持的命令
以上是redis6主要特性以及使用場景的大致介紹,其他像"并發(fā)進行socket讀寫",消息隊列模塊,無磁盤數(shù)據(jù)同步,rdb文件加載速度優(yōu)化等因為篇幅時間有限,就沒有過多描述了
謝謝閱讀!