本發(fā)明涉及數(shù)據(jù)訪問(wèn)技術(shù)領(lǐng)域,尤其涉及一種緩存系統(tǒng)熱點(diǎn)數(shù)據(jù)訪問(wèn)方法。
背景技術(shù):
redis是當(dāng)前企業(yè)廣泛使用的分布式k-v緩存系統(tǒng),在該系統(tǒng)上進(jìn)行讀寫時(shí),會(huì)根據(jù)key的hash計(jì)算出一臺(tái)固定的server來(lái)存取該k-v;因此在實(shí)際應(yīng)用中,某些高峰時(shí)段,會(huì)大量請(qǐng)求同一個(gè)key(可能對(duì)應(yīng)應(yīng)用的某個(gè)促銷商品、熱點(diǎn)新聞、熱點(diǎn)評(píng)論等),根據(jù)key的hash,所有讀請(qǐng)求都將落到同一個(gè)server上,該機(jī)器的負(fù)載就會(huì)嚴(yán)重加劇,此時(shí)整個(gè)系統(tǒng)增加server也沒(méi)有任何用處,因?yàn)楦鶕?jù)hash算法,同一個(gè)key的請(qǐng)求還是會(huì)落到同一臺(tái)新機(jī)器上,該機(jī)器成為系統(tǒng)瓶頸;這個(gè)問(wèn)題稱為“熱點(diǎn)key”問(wèn)題;
解決熱點(diǎn)問(wèn)題有很多辦法,如果不能從業(yè)務(wù)的角度將熱點(diǎn)拆分,那么只能采取多份數(shù)據(jù)的形式分擔(dān)(c/s分?jǐn)偅?wù)端線程間、機(jī)器間、集群間分?jǐn)?;比如用戶如果提前知道某些key可能成為熱點(diǎn),那么客戶端可以提前拆分熱點(diǎn)key;也可以搭建一個(gè)備用集群,寫的時(shí)候雙寫,然后隨機(jī)雙讀;這些方案都有各自的缺點(diǎn);因此,我們提出了一種緩存系統(tǒng)熱點(diǎn)數(shù)據(jù)訪問(wèn)方法用于解決上述問(wèn)題。
技術(shù)實(shí)現(xiàn)要素:
基于背景技術(shù)存在的技術(shù)問(wèn)題,本發(fā)明提出了一種緩存系統(tǒng)熱點(diǎn)數(shù)據(jù)訪問(wèn)方法。
本發(fā)明提出的一種緩存系統(tǒng)熱點(diǎn)數(shù)據(jù)訪問(wèn)方法,包括以下步驟:
s1:在redis的ds上面增加hotkey模塊,默認(rèn)ds啟動(dòng)后開(kāi)啟hotkey模塊,用接口隨時(shí)控制啟停熱點(diǎn)統(tǒng)計(jì)功能,熱點(diǎn)統(tǒng)計(jì)功能啟動(dòng)后,做相關(guān)初始化;
s2:將服務(wù)器識(shí)別熱點(diǎn)的hotkey邏輯加在worker線程里,每個(gè)到達(dá)服務(wù)器的讀請(qǐng)求首先競(jìng)爭(zhēng)一把try鎖,獲取鎖成功后,經(jīng)歷三個(gè)階段,統(tǒng)計(jì)成功經(jīng)過(guò)三個(gè)階段的請(qǐng)求;
s3:當(dāng)服務(wù)器端反饋有熱點(diǎn)產(chǎn)生時(shí),客戶端首先將該feedback包中的key寫入local-cache,同時(shí)開(kāi)啟hot-running模式,該模式下只能寫入服務(wù)端反饋的帶熱點(diǎn)標(biāo)記的key,local-cache中非熱點(diǎn)的key將逐步被淘汰。
優(yōu)選地,所述s1中,ds為dataserver。
優(yōu)選地,所述s1中,相關(guān)初始化包括設(shè)定統(tǒng)計(jì)熱點(diǎn)key時(shí)要關(guān)注的opcode操作序列列表、設(shè)定采樣次數(shù)、設(shè)定熱點(diǎn)qps閾值、設(shè)定服務(wù)器端熱點(diǎn)key容量上限和每個(gè)熱點(diǎn)key在服務(wù)器的生命周期。
優(yōu)選地,所述s2中,三個(gè)階段包括采樣階段、定位階段和查詢階段。
本發(fā)明中,所述一種緩存系統(tǒng)熱點(diǎn)數(shù)據(jù)訪問(wèn)方法在原有集群的基礎(chǔ)上做修改,不改變集群部署,對(duì)應(yīng)用透明;主要分為兩個(gè)模塊服務(wù)端熱點(diǎn)統(tǒng)計(jì)和客戶端localcache邏輯;即在data-server上面運(yùn)行熱點(diǎn)統(tǒng)計(jì)邏輯,對(duì)每個(gè)到達(dá)的讀請(qǐng)求,提取出key進(jìn)行統(tǒng)計(jì),并計(jì)算出當(dāng)前請(qǐng)求中的熱點(diǎn)key,同時(shí)當(dāng)客戶端訪問(wèn)的正好是熱key,則向客戶端回一個(gè)熱點(diǎn)反饋feedback包;客戶端收到feedback包之后,就將攜帶的hot-key寫入客戶端local-cache,同時(shí)拒絕非熱key寫入local-cache,方法簡(jiǎn)單,使用方便。
具體實(shí)施方式
下面結(jié)合具體實(shí)施例對(duì)本發(fā)明作進(jìn)一步解說(shuō)。
實(shí)施例
本實(shí)施例提出了一種緩存系統(tǒng)熱點(diǎn)數(shù)據(jù)訪問(wèn)方法,包括以下步驟:
s1:在redis的ds上面增加hotkey模塊,默認(rèn)ds啟動(dòng)后開(kāi)啟hotkey模塊,用接口隨時(shí)控制啟停熱點(diǎn)統(tǒng)計(jì)功能,熱點(diǎn)統(tǒng)計(jì)功能啟動(dòng)后,做相關(guān)初始化;
s2:將服務(wù)器識(shí)別熱點(diǎn)的hotkey邏輯加在worker線程里,每個(gè)到達(dá)服務(wù)器的讀請(qǐng)求首先競(jìng)爭(zhēng)一把try鎖,獲取鎖成功后,經(jīng)歷三個(gè)階段,統(tǒng)計(jì)成功經(jīng)過(guò)三個(gè)階段的請(qǐng)求;
s3:當(dāng)服務(wù)器端反饋有熱點(diǎn)產(chǎn)生時(shí),客戶端首先將該feedback包中的key寫入local-cache,同時(shí)開(kāi)啟hot-running模式,該模式下只能寫入服務(wù)端反饋的帶熱點(diǎn)標(biāo)記的key,local-cache中非熱點(diǎn)的key將逐步被淘汰。
本實(shí)施例中,s1中,ds為dataserver,s1中,相關(guān)初始化包括設(shè)定統(tǒng)計(jì)熱點(diǎn)key時(shí)要關(guān)注的opcode操作序列列表、設(shè)定采樣次數(shù)、設(shè)定熱點(diǎn)qps閾值、設(shè)定服務(wù)器端熱點(diǎn)key容量上限和每個(gè)熱點(diǎn)key在服務(wù)器的生命周期,s2中,三個(gè)階段包括采樣階段、定位階段和查詢階段,一種緩存系統(tǒng)熱點(diǎn)數(shù)據(jù)訪問(wèn)方法在原有集群的基礎(chǔ)上做修改,不改變集群部署,對(duì)應(yīng)用透明;主要分為兩個(gè)模塊服務(wù)端熱點(diǎn)統(tǒng)計(jì)和客戶端localcache邏輯;即在data-server上面運(yùn)行熱點(diǎn)統(tǒng)計(jì)邏輯,對(duì)每個(gè)到達(dá)的讀請(qǐng)求,提取出key進(jìn)行統(tǒng)計(jì),并計(jì)算出當(dāng)前請(qǐng)求中的熱點(diǎn)key,同時(shí)當(dāng)客戶端訪問(wèn)的正好是熱key,則向客戶端回一個(gè)熱點(diǎn)反饋feedback包;客戶端收到feedback包之后,就將攜帶的hot-key寫入客戶端local-cache,同時(shí)拒絕非熱key寫入local-cache,方法簡(jiǎn)單,使用方便。
本實(shí)施例中,采樣階段包括以下步驟:
s1、判斷本請(qǐng)求的opcode是否在配置的opcode列表里面;
s2、維護(hù)1024個(gè)桶,將每個(gè)請(qǐng)求上的pick-key哈希到桶,記錄每個(gè)桶的命中數(shù),記錄當(dāng)前采樣次數(shù)(redis每個(gè)請(qǐng)求中的key形式會(huì)有pkey-skey、multi-key、single-key等,如何對(duì)他們中的有效部分做統(tǒng)計(jì),后面詳細(xì)敘述,這里統(tǒng)稱有效key為pick-key);
s3、當(dāng)采樣次數(shù)達(dá)到sample_max(服務(wù)器配置)時(shí),計(jì)算這些桶的標(biāo)準(zhǔn)差和均值,同時(shí)記下最大的桶號(hào);
s4、如果這些桶的標(biāo)準(zhǔn)差大于均值的n倍(設(shè)定系數(shù)),則認(rèn)為存在熱點(diǎn),當(dāng)最大的桶號(hào)的qps大于閾值,那么最大的桶號(hào)就是當(dāng)前熱桶,進(jìn)入定位階段,同時(shí)進(jìn)入下一個(gè)采樣周期。
即熱點(diǎn)現(xiàn)象判斷公式為:
所有桶的count計(jì)數(shù)的標(biāo)準(zhǔn)差>這些桶的count計(jì)數(shù)的均值*n(系數(shù))。
定位階段包括以下步驟:
s1、接下來(lái)會(huì)再統(tǒng)計(jì)reap_max次命中了熱桶的請(qǐng)求,計(jì)算出熱桶中的每個(gè)pick-key的訪問(wèn)次數(shù),統(tǒng)計(jì)reap_max次停止;
s2、挑選計(jì)數(shù)最大的x個(gè)pick-key,如果x個(gè)中的某些pick-key的qps大于閾值,則這些key被認(rèn)定為熱key;
s3、將判定為hot的pick-key加入服務(wù)器熱點(diǎn)lru鏈表,同時(shí)進(jìn)入下一個(gè)定位周期,釋放本次try鎖。
查詢階段包括以下步驟:
s1、對(duì)到達(dá)服務(wù)器的每一個(gè)讀請(qǐng)求,都會(huì)取出pick-key,然后查詢服務(wù)器lru鏈表;
s2、如果命中,則對(duì)該pick-key標(biāo)記為熱點(diǎn);
s3、該請(qǐng)求結(jié)束后,會(huì)額外發(fā)送一個(gè)feedback包,攜帶熱點(diǎn)key,通知客戶端;
s4、至此,服務(wù)器hot-key邏輯結(jié)束。
本實(shí)施例依賴于redis客戶端的local-cache,它是redis客戶端自帶的緩存功能,能將寫入服務(wù)器的key-value,緩存在本地讀取,其容量非常有限;使用local-cache需注意以下幾個(gè)細(xì)節(jié)問(wèn)題:
1、localcache與redis-server間如何同步
當(dāng)客戶端打開(kāi)cache功能后,每次寫操作強(qiáng)制刪除本地cache的key,讀操作時(shí),更新后端服務(wù)器的值到本地cache。
2、localcache數(shù)據(jù)淘汰
由于客戶端機(jī)器配置有限,localcache只能緩存部分k-v;因此客戶端localcache有兩種淘汰機(jī)制以防內(nèi)存消耗過(guò)多,過(guò)期淘汰和容量逐出。
過(guò)期淘汰,即當(dāng)讀server操作成功后,更新localcache時(shí),會(huì)將每個(gè)key設(shè)置一個(gè)在localcache中合理的過(guò)期時(shí)間(默認(rèn)30ms);應(yīng)用使用redis客戶端時(shí),大多是多線程訪問(wèn);試想當(dāng)多個(gè)線程發(fā)現(xiàn)某個(gè)key的存活超過(guò)過(guò)期時(shí)間時(shí),會(huì)做什么處理呢?會(huì)有大量請(qǐng)求擊穿localcache,訪問(wèn)后端redis。
為了解決這樣的洪流問(wèn)題,這里加了一個(gè)過(guò)期時(shí)間續(xù)期的操作;當(dāng)多個(gè)線程并發(fā)讀取某個(gè)key時(shí),第一個(gè)競(jìng)爭(zhēng)到鎖的線程會(huì)判斷key的過(guò)期時(shí)間,如果已經(jīng)過(guò)期,則返回null,并對(duì)該key續(xù)期(即延長(zhǎng)過(guò)期時(shí)間),由于返回的是null,該線程會(huì)擊穿localcache繼續(xù)向server發(fā)起請(qǐng)求,并更新本地localcache;其他線程訪問(wèn)key時(shí),已經(jīng)是續(xù)期之后,這些線程的訪問(wèn)該key時(shí),就不會(huì)發(fā)現(xiàn)已經(jīng)過(guò)期,讀到的是老的value,等到第一個(gè)線程完成server端key-value到localcache的更新結(jié)束后,所有線程都將讀到新value;這樣的好處是不會(huì)在某個(gè)key過(guò)期時(shí)間一到就擊穿localcache,并大量的訪問(wèn)server,對(duì)server造成壓力。
3、clone機(jī)制
clone要解決的問(wèn)題是:當(dāng)客戶端需要將key對(duì)應(yīng)的value寫入到localcache時(shí),很多場(chǎng)景需要深clone,以防止同一個(gè)對(duì)象在localcache之外被修改,從而造成localcache中的value與后端server的value不一致。
但是clone操作本身很耗費(fèi)cpu,如果每次往localcache中寫value都需要clone的話,非常影響性能;并且大多數(shù)情況,用戶訪問(wèn)一個(gè)key的機(jī)會(huì)只有一次,比如一個(gè)for迭代循環(huán),每次訪問(wèn)不同(key+i),就需要把每個(gè)key對(duì)應(yīng)的value,clone一次再寫入local-cache中;這樣做有兩個(gè)問(wèn)題:一是非常耗時(shí);二是:并寫入localcache中的k-v沒(méi)有第二次命中的機(jī)會(huì),這是不必要的clone。
因此我們clone的機(jī)制是,第一次寫localcache時(shí),只把null當(dāng)做value寫入;當(dāng)localcache中該key還有第二次機(jī)會(huì)被訪問(wèn)時(shí),客戶端拿到null就會(huì)重新去服務(wù)器讀最新數(shù)據(jù),然后我們就真實(shí)的clone一次服務(wù)端讀到的value并寫入localcache中;我們認(rèn)為該key有第二次讀到就會(huì)有更多次機(jī)會(huì)被讀到。
以上所述,僅為本發(fā)明較佳的具體實(shí)施方式,但本發(fā)明的保護(hù)范圍并不局限于此,任何熟悉本技術(shù)領(lǐng)域的技術(shù)人員在本發(fā)明揭露的技術(shù)范圍內(nèi),根據(jù)本發(fā)明的技術(shù)方案及其發(fā)明構(gòu)思加以等同替換或改變,都應(yīng)涵蓋在本發(fā)明的保護(hù)范圍之內(nèi)。