2020年5月份,6.0版本。
面向網(wǎng)絡處理的多IO線程可以提高網(wǎng)絡請求處理的速度,而客戶端緩存可以讓應用直接在客戶端本地讀取數(shù)據(jù),這兩個特性可以提升Redis的性能。
細粒度權限控制讓Redis可以按照命令粒度控制不同用戶的訪問權限,加強了Redis的安全保護。
RESP 3協(xié)議則增強客戶端的功能,可以讓應用更加方便地使用Redis的不同數(shù)據(jù)類型。
1 從單線程處理網(wǎng)絡請求到多線程處理
Redis單線程架構,雖有些命令操作可用后臺線程或子進程執(zhí)行(如數(shù)據(jù)刪除、快照生成、AOF重寫),但從網(wǎng)絡IO處理到實際的讀寫命令處理,都是由單線程完成。
隨著網(wǎng)絡硬件的性能提升,Redis性能瓶頸有時會出現(xiàn)在網(wǎng)絡I/O處理,即單個主線程處理網(wǎng)絡請求的速度跟不上底層網(wǎng)絡硬件的速度。
一般有兩種方法:
- 用用戶態(tài)網(wǎng)絡協(xié)議棧(例如DPDK)取代內核網(wǎng)絡協(xié)議棧,讓網(wǎng)絡請求的處理不用在內核里執(zhí)行,直接在用戶態(tài)完成處理就行。
讓Redis避免頻繁讓內核進行網(wǎng)絡請求處理,可很好地提升請求處理效率。但這個方法要求在Redis的整體架構中,添加對用戶態(tài)網(wǎng)絡協(xié)議棧的支持,需修改Redis源碼中和網(wǎng)絡相關的部分(例如修改所有的網(wǎng)絡收發(fā)請求函數(shù)),這會帶來很多開發(fā)工作量。而且新增代碼還可能引入新Bug,導致系統(tǒng)不穩(wěn)定。 - 采用多個IO線程來處理網(wǎng)絡請求,提高網(wǎng)絡請求處理的并行度。Redis 6.0采用
Redis的多I/O線程只是用來處理網(wǎng)絡請求,對于讀寫命令,Redis仍使用單線程處理。因為,Redis處理請求時,網(wǎng)絡處理經(jīng)常是瓶頸,通過多個I/O線程并行處理網(wǎng)絡操作,可提升實例的整體處理性能。而繼續(xù)使用單線程執(zhí)行命令操作,無需為了保證Lua腳本、事務的原子性,額外開發(fā)多線程互斥機制了。這樣Redis線程模型實現(xiàn)就簡單了。
6.0中,主線程和IO線程具體是怎么協(xié)作完成請求處理的?
可將主線程和多I/O線程的協(xié)作分成如下階段:
服務端和客戶端建立Socket連接,并分配處理線程
主線程負責接收建立連接請求。當有客戶端請求和實例建立Socket連接時,主線程會創(chuàng)建和客戶端的連接,并把 Socket 放入全局等待隊列中。
緊接著,主線程通過輪詢方法把Socket連接分配給IO線程。
IO線程讀取并解析請求
主線程一旦把Socket分配給IO線程,就會進入阻塞狀態(tài),等待IO線程完成客戶端請求讀取和解析。因為有多個IO線程在并行處理,所以,這個過程很快就可以完成。
主線程執(zhí)行請求操作
等到IO線程解析完請求,主線程還是會以單線程的方式執(zhí)行這些命令操作
IO線程回寫Socket和主線程清空全局隊列
當主線程執(zhí)行完請求操作后,會把需要返回的結果寫入緩沖區(qū),然后,主線程會阻塞等待IO線程把這些結果回寫到Socket中,并返回給客戶端。
和IO線程讀取和解析請求一樣,IO線程回寫Socket時,也是有多個線程在并發(fā)執(zhí)行,所以回寫Socket的速度也很快。等到IO線程回寫Socket完畢,主線程會清空全局隊列,等待客戶端的后續(xù)請求。
該階段主線程和IO線程的操作:
2 啟用多線程
6.0多線程機制默認關閉,要啟用,需在redis.conf中完成兩個設置:
1.設置io-threads-do-reads
=yes,表示啟用多線程。
io-threads-do-reads yes
2.設置線程個數(shù)。線程個數(shù)一般小于Redis實例所在機器的CPU核數(shù)。如8核機器,Redis官方建議6個IO線程。
io-threads 6
若你在實際應用中,發(fā)現(xiàn)Redis實例CPU開銷不大,吞吐量卻沒提升,可考慮使用Redis 6.0的多線程機制,加速網(wǎng)絡處理,提升實例吞吐量。
3 實現(xiàn)服務端協(xié)助的客戶端緩存
6.0實現(xiàn)了服務端協(xié)助的客戶端緩存功能,也稱跟蹤(Tracking)功能。業(yè)務應用中的Redis客戶端就能將讀取的數(shù)據(jù)緩存在業(yè)務應用本地,應用就能直接在本地快速讀取數(shù)據(jù)。
問題也來了,若數(shù)據(jù)被修改或失效,如何通知客戶端對緩存的數(shù)據(jù)做失效處理?6.0實現(xiàn)的Tracking功能提供兩種模式解決這問題。
3.1 普通模式
實例會在服務端記錄客戶端讀取過的key,并監(jiān)測key是否有修改。一旦key值變化,服務端會給客戶端發(fā)送invalidate消息,通知客戶端緩存失效
服務端對記錄的key只會報告一次invalidate消息,也就是說,服務端在給客戶端發(fā)送過一次invalidate消息后,如果key再被修改,此時,服務端就不會再次給客戶端發(fā)送invalidate消息。
只有當客戶端再次執(zhí)行讀命令時,服務端才會再次監(jiān)測被讀取的key,并在key修改時發(fā)送invalidate消息。這樣設計的考慮是節(jié)省有限的內存空間。畢竟,如果客戶端不再訪問這個key了,而服務端仍然記錄key的修改情況,就會浪費內存資源。
我們可以通過執(zhí)行下面的命令,打開或關閉普通模式下的Tracking功能。
CLIENT TRACKING ON|OFF
3.2 廣播模式
服務端會給客戶端廣播所有key的失效情況,但這樣做后,若K被頻繁修改,服務端會發(fā)送大量失效廣播消息,消耗大量網(wǎng)絡帶寬資源。
實際應用時,會讓客戶端注冊希望跟蹤的key的前綴,當帶有注冊前綴的K被修改時,服務端會把失效消息廣播給所有注冊的客戶端。和普通模式不同,在廣播模式下,即使客戶端還沒讀取過K,但只要它注冊了要跟蹤的K,服務端都會把K失效消息通知給這客戶端。
案例 -客戶端如何使用廣播模式接收key失效消息
當我們在客戶端執(zhí)行下面的命令后,如果服務端更新了user??1003這個key,那么,客戶端就會收到invalidate消息。
CLIENT TRACKING ON BCAST PREFIX user
這種監(jiān)測帶有前綴的key的廣播模式,和我們對key的命名規(guī)范非常匹配。我們在實際應用時,會給同一業(yè)務下的key設置相同的業(yè)務名前綴,所以,我們就可以非常方便地使用廣播模式。
普通模式和廣播模式,需要客戶端使用RESP 3協(xié)議,RESP 3協(xié)議是6.0新啟用的通信協(xié)議。
對于使用RESP 2協(xié)議的客戶端來說,就需要使用另一種模式:
重定向模式(redirect)
想獲得失效消息通知的客戶端,需執(zhí)行訂閱命令SUBSCRIBE,專門訂閱用于發(fā)送失效消息的頻道_redis_:invalidate。同時使用另外一個客戶端,執(zhí)行CLIENT TRACKING,設置服務端將失效消息轉發(fā)給使用RESP 2協(xié)議的客戶端。
案例
如何讓使用RESP 2協(xié)議的客戶端也能接受失效消息?
假設客戶端B想獲取失效消息,但客戶端B只支持RESP 2協(xié)議,客戶端A支持RESP 3協(xié)議。我們可以分別在客戶端B和A上執(zhí)行SUBSCRIBE和CLIENT TRACKING,如下所示:
//客戶端B執(zhí)行,客戶端B的ID號是303
SUBSCRIBE _redis_:invalidate
//客戶端A執(zhí)行
CLIENT TRACKING ON BCAST REDIRECT 303
這樣設置以后,如果有鍵值對被修改了,客戶端B就可以通過_redis_:invalidate頻道,獲得失效消息了。
4 從簡單的基于密碼訪問到細粒度的權限控制
實例的訪問權限控制列表功能(Access Control List,ACL),這個特性可以有效地提升Redis的使用安全性。
在Redis 6.0 版本之前,要想實現(xiàn)實例的安全訪問,只能通過設置密碼來控制,例如,客戶端連接實例前需要輸入密碼。
此外,對于一些高風險的命令(例如KEYS、FLUSHDB、FLUSHALL等),在Redis 6.0 之前,我們也只能通過rename-command來重新命名這些命令,避免客戶端直接調用。
Redis 6.0 提供了更加細粒度的訪問權限控制,這主要有兩方面的體現(xiàn)。
首先,6.0版本支持創(chuàng)建不同用戶來使用Redis。在6.0版本前,所有客戶端可以使用同一個密碼進行登錄使用,但是沒有用戶的概念,而在6.0中,我們可以使用ACL SETUSER命令創(chuàng)建用戶。例如,我們可以執(zhí)行下面的命令,創(chuàng)建并啟用一個用戶normaluser,把它的密碼設置為“abc”:
ACL SETUSER normaluser on > abc
另外,6.0版本還支持以用戶為粒度設置命令操作的訪問權限。我把具體操作列在了下表中,你可以看下,其中,加號(+)和減號(-)就分別表示給用戶賦予或撤銷命令的調用權限。
為了便于你理解,我給你舉個例子。假設我們要設置用戶normaluser只能調用Hash類型的命令操作,而不能調用String類型的命令操作,我們可以執(zhí)行如下命令:
ACL SETUSER normaluser +@hash -@string
除了設置某個命令或某類命令的訪問控制權限,6.0版本還支持以key為粒度設置訪問權限。
具體的做法是使用波浪號“~”和key的前綴來表示控制訪問的key。例如,我們執(zhí)行下面命令,就可以設置用戶normaluser只能對以“user:”為前綴的key進行命令操作:
ACL SETUSER normaluser ~user:* +@all
好了,到這里,你了解了,Redis 6.0可以設置不同用戶來訪問實例,而且可以基于用戶和key的粒度,設置某個用戶對某些key允許或禁止執(zhí)行的命令操作。
這樣一來,我們在有多用戶的Redis應用場景下,就可以非常方便和靈活地為不同用戶設置不同級別的命令操作權限了,這對于提供安全的Redis訪問非常有幫助。
5 啟用RESP 3協(xié)議
Redis 6.0實現(xiàn)了RESP 3通信協(xié)議,而之前都是使用的RESP 2。在RESP 2中,客戶端和服務器端的通信內容都是以字節(jié)數(shù)組形式進行編碼的,客戶端需要根據(jù)操作的命令或是數(shù)據(jù)類型自行對傳輸?shù)臄?shù)據(jù)進行解碼,增加了客戶端開發(fā)復雜度。
而RESP 3直接支持多種數(shù)據(jù)類型的區(qū)分編碼,包括空值、浮點數(shù)、布爾值、有序的字典集合、無序的集合等。
所謂區(qū)分編碼,就是指直接通過不同的開頭字符,區(qū)分不同的數(shù)據(jù)類型,這樣一來,客戶端就可以直接通過判斷傳遞消息的開頭字符,來實現(xiàn)數(shù)據(jù)轉換操作了,提升了客戶端的效率。除此之外,RESP 3協(xié)議還可以支持客戶端以普通模式和廣播模式實現(xiàn)客戶端緩存。文章來源:http://www.zghlxwxcb.cn/news/detail-624958.html
6 總結
Redis 6.0是剛剛推出的,新的功能特性還需要在實際應用中進行部署和驗證,所以,如果你想試用Redis 6.0,可以嘗試先在非核心業(yè)務上使用Redis 6.0:文章來源地址http://www.zghlxwxcb.cn/news/detail-624958.html
- 可以驗證新特性帶來的性能或功能優(yōu)勢
- 避免因為新特性不穩(wěn)定而導致核心業(yè)務受到影響
到了這里,關于Redis 6.0的新特性:多線程、客戶端緩存與安全的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!