




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
源碼5: 步——探索「跳 Redis的t是?個(gè)復(fù)合結(jié)構(gòu),???它需要?個(gè)he和scoe的對(duì)應(yīng)關(guān)系,另???需要提供按照sce來排序的功能,還需要能夠指定e的范圍來獲取ezset的實(shí)現(xiàn)是?個(gè)hash字典加?個(gè)跳躍列表(skiplist)。hash結(jié)構(gòu)在講字典結(jié)構(gòu)時(shí)已經(jīng)詳細(xì)分析過了,它很類似于Java語?中的HashMap結(jié)構(gòu)。本節(jié)來講跳躍列表,它?較復(fù)雜,讀者要有?上圖就是跳躍列表的示意圖,圖中只畫了四層,Redis的跳躍表共有64層,容納2^64個(gè)元素應(yīng)該不成問題。每?個(gè)kv塊對(duì)應(yīng)的結(jié)構(gòu)如下?的代碼中的zslnode結(jié)構(gòu),kvheader也是這個(gè)結(jié)構(gòu),只不過value字段是null值——?效的,score是?來墊底的。kv之間使?指針串起來形成了雙向鏈表結(jié)構(gòu),它們是有序排列的,從?到?。不同的kv層?可能不?樣,層數(shù)越?的kvkv會(huì)使?指針串起來。每?個(gè)層元素的遍歷都是從kvheader出發(fā)。structstruct{stringvalue;doublescore;zslnode*[forwards;zslnode*backward;}structzslzslnode*headerintmaxLevelmap<stringzslnode*hthash}位置節(jié)點(diǎn)(定位到最后?個(gè)?「 復(fù)雜度將會(huì)降到O(lg(n))。 要定位到那個(gè)紫?的kv,需要從header的最?層開始遍歷找到第?個(gè)節(jié)點(diǎn)(最后?個(gè)?「 節(jié)點(diǎn)開始降?層再遍歷找到第?個(gè)節(jié)點(diǎn)(最后?個(gè)?「 有了這個(gè)搜索路徑,就可以插?這個(gè)新節(jié)點(diǎn)了。不過這個(gè)插?過理的層數(shù)。直觀上期望的?標(biāo)是50%的Level1,25%的Level2,12.5%的Level3,?直到最頂層2^-63,因?yàn)檫@?每?層的晉升概率是50%。/*Returnsarandomlevelforthenewskiplistnodewearegoingtocreate.Thereturnvalueofthisfunctionisbetween1andZSKIPLIST_MAXLEVEL lusive),withapowerlaw-alikedistributionwherehigherlevelsarelesslikelytobereturned.*/intzslRandomLevel(void){intlevel=while((random()&0xFFFF)<(ZSKIPLIST_P*level+=return(level<ZSKIPLIST_MAXLEVEL)?level:}不過Redis標(biāo)準(zhǔn)源碼中的晉升概率只有25%,也就是代碼中的ZSKIPLIST_P的值。所以官?的跳躍列表更加的扁平化,層?相對(duì)較常浪費(fèi)。跳躍列表會(huì)記錄?下當(dāng)前的最?層數(shù)maxLevel,遍歷時(shí)從這個(gè)maxLevel開始遍歷性能就會(huì)提?很多。/*/*Insertanewnodeintheskiplist.Assumestheelementdoesnotalready*exist(uptothecallertoen that).TheskiplisttakesownershipofthepassedSDSstring'ele'.*/zskiplistNode*zslInsert(zskiplist*zsl,doublescore,sdsele){//搜索路zskiplistNode//經(jīng)過的節(jié)點(diǎn)跨unsignedintinti,x=zsl->header;for(i=zsl->level-1;i>=0;i--)/*storerankthatiscrossedtoreachtheinsertposition*/rank[i]=i==(zsl->level-1)?0:如果score相等,還需要?較while(x->level[i].forwardscore==score>ele,ele)<{
rank[i]+=x->level[i].span;x=x->level[i].forward;}update[i]=}/*weassumetheelementisnotalreadyinside,seweallowduplicatedscores,reinsertingthesameelementshouldneverhappensethecallerofzslInsert()shouldtestinthehashtableiftheelementisalreadyinsideornot.level=if(level>zsl->level)for(i=zsl->level;i<level;{rank[i]=0;update[i]=zsl->header;update[i]->level[i].span=}
}zsl->level=x=for(i=0;i<level;i++)x->level[i].forward=update[i]->level[i].forward=/*updatespancoveredbyupdate[i]asxisinsertedhere*/x->level[i].span=>level[i].span-(rank[0]-rank[i]);update[i]->level[i].span=(rank[0]-rank[i])+ rementspanforuntouchedlevels*/for(i=level;i<zsl->level;i++){x->backward=(update[0]==zsl->header)NULL:if(x-x->level[0].forward->backward=zsl->tail=return 調(diào)?zadd?法時(shí),如果對(duì)應(yīng)的value不存在,那就是插?過程。如果這個(gè)value已經(jīng)存在了,只是調(diào)整?下score的值,那就需要??個(gè)更新的流程。假設(shè)這個(gè)新的score值不會(huì)帶來排序位置上的改變,那么就不需要調(diào)整位置,直接修改元素的score值就/*Removeandre-insertwhenscorechanges.*/if(score!=curscore){zskiplistNode*node;znode=zslInsert(zs-/*Wereusedthenode->eleSDSthenode ezslInsertcreatedanewone.*/node->ele=NULL; /*Notethatwedidnotremovedtheoriginalelementfromthehashtablerepresentingthesortedset,sowejustupdatethescore.dictGetVal(de)=&znode->score;/*Updatescoreptr.*/*flags|=}return次路徑搜索。Redis就是這么?的。不過Redis遇到score置是否需要調(diào)整,從這點(diǎn)看,Redis的zadd的代碼似乎還有優(yōu)化空如果score在?個(gè)的情況下,zset中所有的score值都是?樣的,zset的查找性能會(huì)為O(n)么?Redis作者?然考慮到了這?點(diǎn),所以zset的排序元素不只看score值,如果score值相同還需要再?較value值(字符串?較)。 zset可以獲取元素的rank。那這個(gè)rank是如何算出來的?如果僅僅使?上?的結(jié)構(gòu),rank是不能算出來的。Redis在skiplist的forward指針上進(jìn)?了優(yōu)化,給每?個(gè)forward指針都增加了span屬性,span是「跨度」的意思,表示從前?個(gè)節(jié)點(diǎn)沿著當(dāng)前層的forward指針跳到當(dāng)前這個(gè)節(jié)點(diǎn)中間會(huì)跳過多少個(gè)節(jié)點(diǎn)。Redis在插?刪除操作時(shí)會(huì)??翼翼地更新span值的??。structstruct{zslnode*item;longspan;跨度}struct{Stringvalue;doublescore;zslforward*[forwards;zslnode*backward;} 要計(jì)算?個(gè)元素的時(shí),只需要將「搜索路徑」上的經(jīng)過的所有節(jié)點(diǎn)的跨度span值進(jìn)?疊加就可以算出元素的最終rank 提到當(dāng)score值的變化微?,不會(huì)帶來位置上的調(diào)整時(shí),是不是可以直接修改score后就返回?作者Antirez提
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 高層土方施工方案
- 樓板管口灌漿施工方案
- 房產(chǎn)委托代理合同
- 旅游酒店業(yè)智慧客房服務(wù)系統(tǒng)建設(shè)方案
- 橋梁基礎(chǔ)注漿施工方案
- 鐵藝別墅施工方案
- 冷凍機(jī)房施工方案
- 低壓柜施工方案
- phc靜壓樁施工方案
- 順德瀝青鋪路工程施工方案
- 理療課件教學(xué)課件
- 商業(yè)秘密保護(hù)管理辦法
- 2024解析:第十二章滑輪-講核心(解析版)
- 2022年高考真題-政治(重慶卷) 含答案
- 人教PEP版(一起)(2024)一年級(jí)上冊(cè)英語全冊(cè)教案(單元整體教學(xué)設(shè)計(jì))
- 2024 年下半年數(shù)學(xué)一年級(jí)數(shù)學(xué)思維挑戰(zhàn)試卷
- 短視頻內(nèi)容課件
- 學(xué)會(huì)管理和控制自己課件
- 語文修改語病-五年(高考2020至2024)修改病句真題詳盡解析
- 2024年中國木制床頭柜市場調(diào)查研究報(bào)告
- 成人有創(chuàng)機(jī)械通氣氣道內(nèi)吸引技術(shù)操作標(biāo)準(zhǔn)解讀
評(píng)論
0/150
提交評(píng)論