實(shí)戰(zhàn)1|使用分布式緩存Redis實(shí)現(xiàn)熱點(diǎn)資源順序訪問
應(yīng)用現(xiàn)狀
在傳統(tǒng)單機(jī)部署的情況下,可以使用Java并發(fā)處理相關(guān)的API(如ReentrantLock或synchronized)進(jìn)行互斥控制。這種Java提供的原生鎖機(jī)制可以保證在同一個(gè)Java虛擬機(jī)進(jìn)程內(nèi)的多個(gè)線程同步執(zhí)行,避免出現(xiàn)無序現(xiàn)象。
但在互聯(lián)網(wǎng)場(chǎng)景,如商品秒殺中,隨著整個(gè)系統(tǒng)的并發(fā)飆升,需要多臺(tái)機(jī)器并發(fā)運(yùn)行,假設(shè)此時(shí)兩個(gè)用戶的請(qǐng)求同時(shí)到來,但落在了不同的機(jī)器上,雖然這兩個(gè)請(qǐng)求是可以同時(shí)執(zhí)行,但是因?yàn)閮蓚€(gè)機(jī)器運(yùn)行在兩個(gè)不同的Java虛擬機(jī)里面,他們加的鎖只對(duì)屬于自己Java虛擬機(jī)里面的線程有效,對(duì)于其他Java虛擬機(jī)的線程是無效的。因此,Java提供的原生鎖機(jī)制在多機(jī)部署場(chǎng)景下失效了,這是因?yàn)閮膳_(tái)機(jī)器加的鎖不是同一個(gè)鎖(兩個(gè)鎖在不同的Java虛擬機(jī)里面),這樣便會(huì)出現(xiàn)庫存超賣的現(xiàn)象。
解決方案
基于存在的現(xiàn)狀,我們只要保證兩臺(tái)機(jī)器加的鎖是同一個(gè)鎖,用加鎖的方式對(duì)某種資源進(jìn)行順序訪問控制。這就需要分布式鎖登場(chǎng)了。
分布式鎖的思路是:在整個(gè)系統(tǒng)提供一個(gè)全局、唯一的獲取鎖的“東西”,然后每個(gè)系統(tǒng)在需要加鎖時(shí),都去問這個(gè)“東西”拿到一把鎖,這樣不同的系統(tǒng)拿到的就可以認(rèn)為是同一把鎖。
當(dāng)前分布式加鎖主要有三種方式:(磁盤)數(shù)據(jù)庫、緩存數(shù)據(jù)庫、Zookeeper。
使用分布式緩存服務(wù)中Redis類型的緩存實(shí)例實(shí)現(xiàn)分布式加鎖,有幾大優(yōu)勢(shì):
1、加鎖操作簡(jiǎn)單,使用SET、GET、DEL等幾條簡(jiǎn)單命令即可實(shí)現(xiàn)鎖的獲取和釋放。
2、性能優(yōu)越,緩存數(shù)據(jù)的讀寫優(yōu)于磁盤數(shù)據(jù)庫與Zookeeper。
3、可靠性強(qiáng),分布式緩存Redis有主備和集群實(shí)例類型,避免單點(diǎn)故障。
對(duì)分布式應(yīng)用加鎖,能夠避免出現(xiàn)庫存超賣及無序訪問等現(xiàn)象,實(shí)戰(zhàn):如何使用Redis對(duì)分布式應(yīng)用加鎖。
前提條件
1、已購買彈性云服務(wù)器(ECS)且系統(tǒng)類型為Windows。
2、在ECS上安裝JDK1.8以上版本和Eclipse,下載jedis客戶端(點(diǎn)此處直接下載jar包)。
3、已購買分布式緩存Redis緩存實(shí)例且和ECS選擇相同虛擬私有云、子網(wǎng)以及安全組。
操作步驟
1、在ECS上運(yùn)行Eclipse,創(chuàng)建一個(gè)java工程,為示例代碼分別創(chuàng)建一個(gè)分布式鎖實(shí)現(xiàn)類DistributedLock.java和測(cè)試類CaseTest.java,將jedis客戶端作為libs引用到工程中。
2、將分布式緩存Redis緩存實(shí)例的連接地址、端口以及連接密碼配置到分布式鎖實(shí)現(xiàn)類DistributedLock.java示例代碼文件中。在DistributedLock.java中,host及port配置為實(shí)例的連接地址及端口號(hào),在getLockWithTimeout、releaseLock方法中需配置passwd值為實(shí)例訪問密碼。
3、將測(cè)試類CaseTest中加鎖部分注釋掉,變成無鎖情況。
4、編譯及運(yùn)行無鎖的類,運(yùn)行結(jié)果是搶購無序的。
5、取消測(cè)試類CaseTest中注釋的加鎖內(nèi)容,編譯并運(yùn)行得到有序的搶購。
詳細(xì)步驟及代碼詳情請(qǐng)參考:使用DCS實(shí)現(xiàn)熱點(diǎn)資源順序訪問
實(shí)戰(zhàn)3|使用分布式緩存Redis快速搭建高性能緩存服務(wù)
華為云分布式緩存服務(wù)DCS,提供單機(jī)、主備、集群等豐富的緩存類型,滿足用戶高讀寫性能及快速數(shù)據(jù)訪問的業(yè)務(wù)訴求。華為云控制臺(tái)提供一鍵式創(chuàng)建緩存實(shí)例,以及豐富的實(shí)例管理操作,幫助用戶省去運(yùn)維煩惱。如何創(chuàng)建并連接一個(gè)Redis緩存實(shí)例為例,帶大家快速上手分布式緩存技術(shù)。
準(zhǔn)備環(huán)境
登錄華為云控制臺(tái)。在控制臺(tái)頁面中選擇“網(wǎng)絡(luò)> 虛擬私有云”,創(chuàng)建VPC(虛擬私有云),用于對(duì)緩存實(shí)例進(jìn)行安全網(wǎng)絡(luò)隔離。
在控制臺(tái)頁面中選擇“計(jì)算> 彈性云服務(wù)器”,創(chuàng)建一臺(tái)彈性云服務(wù)器(ECS),用于下載客戶端連接緩存實(shí)例。
創(chuàng)建實(shí)例
登錄華為云控制臺(tái),選擇“應(yīng)用服務(wù)> 分布式緩存服務(wù)”,選擇計(jì)費(fèi)模式。
在DCS總覽頁面,單擊“購買緩存實(shí)例”,選擇實(shí)例配置,創(chuàng)建實(shí)例。
連接緩存實(shí)例
緩存實(shí)例創(chuàng)建成功后,在DCS實(shí)例管理頁找到實(shí)例連接地址和端口。
登錄ECS,下載和安裝客戶端。
連接實(shí)例。
讀寫緩存數(shù)據(jù)。
上述就是創(chuàng)建并連接一個(gè)Redis緩存實(shí)例為例的教程,快來創(chuàng)建一個(gè)高性能的服務(wù)吧。
了解詳情:點(diǎn)擊此處前往
實(shí)戰(zhàn)2|使用分布式緩存Redis實(shí)現(xiàn)排行榜功能
場(chǎng)景介紹
在網(wǎng)頁和APP中常常需要用到榜單的功能,對(duì)某個(gè)key-value的列表進(jìn)行降序顯示。當(dāng)操作和查詢并發(fā)大的時(shí)候,使用傳統(tǒng)數(shù)據(jù)庫就會(huì)遇到性能瓶頸,造成較大的時(shí)延。
使用分布式緩存服務(wù)(DCS)的Redis版本,可以實(shí)現(xiàn)一個(gè)商品熱銷排行榜的功能。它的優(yōu)勢(shì)在于:
數(shù)據(jù)保存在緩存中,讀寫速度非常快。
提供字符串(String)、鏈表(List)、集合(Set)、哈希(Hash)等多種數(shù)據(jù)結(jié)構(gòu)類型的存儲(chǔ)。
實(shí)踐指導(dǎo)
1、準(zhǔn)備一臺(tái)彈性云服務(wù)器(ECS),選擇Windows系統(tǒng)類型。
2、在ECS上安裝JDK1.8以上版本和Eclipse,下載jedis客戶端(點(diǎn)此處直接下載jar包)。
3、在華為云控制臺(tái)購買DCS緩存實(shí)例。注意和ECS選擇相同虛擬私有云、子網(wǎng)以及安全組。
4、在ECS上運(yùn)行Eclipse,創(chuàng)建一個(gè)java工程,為示例代碼創(chuàng)建一個(gè)productSalesRankDemo.java文件,并將jedis客戶端作為library引用到工程中。
5、將DCS緩存實(shí)例的連接地址、端口以及連接密碼配置到示例代碼文件中。
6、編譯并運(yùn)行得到結(jié)果。
代碼示例參考:點(diǎn)擊這里前往代碼示例
運(yùn)行結(jié)果
編譯并運(yùn)行以上Demo程序,運(yùn)行結(jié)果:點(diǎn)擊這里前往運(yùn)行結(jié)果
實(shí)戰(zhàn)4|如何發(fā)現(xiàn)和處理大Key和熱Key
如何處理優(yōu)化大Key和熱Key
大Key
進(jìn)行大Key拆分,分為以下幾種場(chǎng)景:
該對(duì)象為String類型的大Key:可以嘗試將對(duì)象分拆成幾個(gè)Key-Value, 使用MGET或者多個(gè)GET組成的pipeline獲取值,分拆單次操作的壓力,對(duì)于集群來說可以將操作壓力平攤到多個(gè)分片上,降低對(duì)單個(gè)分片的影響。
該對(duì)象為集合類型的大Key,并且需要整存整取:在設(shè)計(jì)上嚴(yán)格禁止這種場(chǎng)景的出現(xiàn),因?yàn)闊o法拆分。有效的方法是將該大Key從Redis去除,單獨(dú)放到其余存儲(chǔ)介質(zhì)上。
該對(duì)象為集合類型的大Key,每次只需操作部分元素:將集合類型中的元素分拆。以Hash類型為例,可以在客戶端定義一個(gè)分拆Key的數(shù)量N,每次對(duì)HGET和HSET操作的field計(jì)算哈希值并取模N,確定該field落在哪個(gè)Key上,實(shí)現(xiàn)上類似于Redis Cluster的計(jì)算slot的算法。
將大Key單獨(dú)轉(zhuǎn)移到其余存儲(chǔ)介質(zhì)。
無法拆分的大Key建議使用此方法,將不適用Redis能力的數(shù)據(jù)存至其它存儲(chǔ)介質(zhì),如SFS或者其余NoSQL數(shù)據(jù)庫,并在Redis中刪除該大Key。
注意:禁止使用DEL直接刪除大Key,可能會(huì)造成Redis阻塞,甚至主備倒換。
合理設(shè)置過期時(shí)間并對(duì)過期數(shù)據(jù)定期清理。
合理設(shè)置過期時(shí)間,避免歷史數(shù)據(jù)在Redis中大量堆積。由于Redis的惰性刪除策略,過期數(shù)據(jù)可能并不能及時(shí)清理,如果發(fā)現(xiàn)Redis過期Key清理較慢,建議配置過期Key掃描。
熱Key
使用讀寫分離。
如果熱Key主要是讀流量較大,則可以在客戶端配置讀寫分離,降低對(duì)主節(jié)點(diǎn)的影響。還可以增加多個(gè)副本以滿足讀需求,但是備機(jī)較多也有相應(yīng)的影響,華為云DCS主備節(jié)點(diǎn)之間使用的是星型復(fù)制,即所有的備節(jié)點(diǎn)都直接和主節(jié)點(diǎn)保持同步,這樣能保證備節(jié)點(diǎn)之間相互獨(dú)立,且復(fù)制延遲較小。缺點(diǎn)是在備節(jié)點(diǎn)數(shù)量較多的情況下,主節(jié)點(diǎn)的CPU和網(wǎng)絡(luò)負(fù)載會(huì)較高。
使用客戶端緩存/本地緩存。
該方案需要提前了解業(yè)務(wù)的熱點(diǎn)Key有哪些,設(shè)計(jì)客戶端/本地和遠(yuǎn)端Redis的兩級(jí)緩存架構(gòu),熱點(diǎn)數(shù)據(jù)優(yōu)先從本地緩存獲取,寫入時(shí)同時(shí)更新,這樣能夠分擔(dān)熱點(diǎn)數(shù)據(jù)的大部分讀壓力。缺點(diǎn)是需要修改客戶端架構(gòu)和代碼,改造成本較高。
設(shè)計(jì)熔斷。
熱Key極易造成緩存擊穿,高峰期請(qǐng)求都直接透?jìng)鞯胶蠖藬?shù)據(jù)庫上,從而導(dǎo)致業(yè)務(wù)雪崩。因此熱Key的優(yōu)化一定需要設(shè)計(jì)系統(tǒng)的熔斷,在發(fā)生擊穿的場(chǎng)景下進(jìn)行限流和服務(wù)下調(diào),保護(hù)系統(tǒng)的可用性。
如何發(fā)現(xiàn)大Key和熱Key
|
方法
|
說明
|
|---|---|
使用分布式緩存服務(wù)DCS自帶的大Key和熱Key分析工具進(jìn)行分析 |
請(qǐng)參考分析Redis實(shí)例大Key和熱Key。 |
通過redis-cli的bigkeys和hotkeys參數(shù)查找大Key和熱Key |
1、Redis-cli提供了bigkeys參數(shù),能夠使redis-cli以遍歷的方式分析Redis實(shí)例中的所有Key,并返回Key的整體統(tǒng)計(jì)信息與每個(gè)數(shù)據(jù)類型中Top1的大Key,bigkeys僅能分析并輸入六種數(shù)據(jù)類型(STRING、LIST、HASH、SET、ZSET、STREAM),命令示例為:redis-cli -h <實(shí)例的連接地址> -p <端口> -a <密碼> --bigkeys。 2、自Redis 4.0版本起,redis-cli提供了hotkeys參數(shù),可以快速幫您找出業(yè)務(wù)中的熱Key,該命令需要在業(yè)務(wù)實(shí)際運(yùn)行期間執(zhí)行,以統(tǒng)計(jì)運(yùn)行期間的熱Key。命令示例為:redis-cli -h <實(shí)例的連接地址> -p <端口> -a <密碼> --hotkeys。熱Key的詳情可以在結(jié)果中的summary部分獲取到。 |
通過Redis命令查找大Key |
如果有已知的大Key模式,例如知道其前綴為huaweicloud:msg:test,那么可以通過一個(gè)程序,SCAN符合該前綴的Key,然后通過查詢成員數(shù)量和查詢Key大小的相關(guān)命令,來判斷具體的大Key。 1、查詢成員數(shù)量的相關(guān)命令:LLEN,HLEN,XLEN,ZCARD,SCARD 2、查詢Key占用內(nèi)存大小的命令:DEBUG OBJECT,MEMORY USAGE 注意: 該方法會(huì)大量消耗計(jì)算資源,請(qǐng)知曉并評(píng)估其風(fēng)險(xiǎn),不要在業(yè)務(wù)壓力較大的實(shí)例使用該方法,否則可能會(huì)對(duì)正常業(yè)務(wù)造成影響。 |
通過redis-rdb-tools工具找出大Key |
redis-rdb-tools是分析Redis RDB快照文件的開源工具??梢愿鶕?jù)需求自定義分析Redis實(shí)例中所有Key的內(nèi)存占用情況。 使用此方法需要在分布式緩存服務(wù)DCS實(shí)例備份與恢復(fù)頁簽中導(dǎo)出實(shí)例的rdb文件。 注意: 該方法時(shí)效性相較于在線分析來說較差,優(yōu)勢(shì)在于完全不影響現(xiàn)有業(yè)務(wù)。 |
分布式緩存服務(wù)教程視頻
分布式緩存服務(wù)DCS
04:53
分布式緩存服務(wù)DCS
03:40
分布式緩存服務(wù)DCS
04:16