真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

?Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程-創(chuàng)新互聯(lián)

Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程

站在用戶的角度思考問題,與客戶深入溝通,找到連城網(wǎng)站設(shè)計(jì)與連城網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、空間域名、網(wǎng)站空間、企業(yè)郵箱。業(yè)務(wù)覆蓋連城地區(qū)。

Redis有5個(gè)基本數(shù)據(jù)結(jié)構(gòu),string、list、hash、set和zset。它們是日常開發(fā)中使用頻率非常高應(yīng)用最為廣泛的數(shù)據(jù)結(jié)構(gòu),把這5個(gè)數(shù)據(jù)結(jié)構(gòu)都吃透了,你就掌握了Redis應(yīng)用知識的一半了。

string

?Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程

首先我們從string談起。string表示的是一個(gè)可變的字節(jié)數(shù)組,我們初始化字符串的內(nèi)容、可以拿到字符串的長度,可以獲取string的子串,可以覆蓋string的子串內(nèi)容,可以追加子串。

?Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程

Redis的字符串是動(dòng)態(tài)字符串,是可以修改的字符串,內(nèi)部結(jié)構(gòu)實(shí)現(xiàn)上類似于Java的ArrayList,采用預(yù)分配冗余空間的方式來減少內(nèi)存的頻繁分配,如圖中所示,內(nèi)部為當(dāng)前字符串實(shí)際分配的空間capacity一般要高于實(shí)際字符串長度len。當(dāng)字符串長度小于1M時(shí),擴(kuò)容都是加倍現(xiàn)有的空間,如果超過1M,擴(kuò)容時(shí)一次只會多擴(kuò)1M的空間。需要注意的是字符串大長度為512M。

初始化字符串?需要提供「變量名稱」和「變量的內(nèi)容」

>?set?ireader?beijing.zhangyue.keji.gufen.youxian.gongsi?OK?復(fù)制代碼

獲取字符串的內(nèi)容?提供「變量名稱」

>?get?ireader?"beijing.zhangyue.keji.gufen.youxian.gongsi"?復(fù)制代碼

獲取字符串的長度?提供「變量名稱」

>?strlen?ireader?(integer)?42?復(fù)制代碼

獲取子串?提供「變量名稱」以及開始和結(jié)束位置[start, end]

>?getrange?ireader?28?34?"youxian"?復(fù)制代碼

覆蓋子串?提供「變量名稱」以及開始位置和目標(biāo)子串

>?setrange?ireader?28?wooxian?(integer)?42??#?返回長度?>?get?ireader?"beijing.zhangyue.keji.gufen.wooxian.gongsi"?復(fù)制代碼

追加子串

>?append?ireader?.hao?(integer)?46?#?返回長度?>?get?ireader?"beijing.zhangyue.keji.gufen.wooxian.gongsi.hao"?復(fù)制代碼

遺憾的是字符串沒有提供字串插入方法和子串刪除方法。

計(jì)數(shù)器?如果字符串的內(nèi)容是一個(gè)整數(shù),那么還可以將字符串當(dāng)成計(jì)數(shù)器來使用。

>?set?ireader?42?OK?>?get?ireader?"42"?>?incrby?ireader?100?(integer)?142?>?get?ireader?"142"?>?decrby?ireader?100?(integer)?42?>?get?ireader?"42"?>?incr?ireader??#?等價(jià)于incrby?ireader?1?(integer)?43?>?decr?ireader??#?等價(jià)于decrby?ireader?1?(integer)?42?復(fù)制代碼

計(jì)數(shù)器是有范圍的,它不能超過Long.Max,不能低于Long.MIN

>?set?ireader?9223372036854775807?OK?>?incr?ireader?(error)?ERR?increment?or?decrement?would?overflow?>?set?ireader?-9223372036854775808?OK?>?decr?ireader?(error)?ERR?increment?or?decrement?would?overflow?復(fù)制代碼

過期和刪除?字符串可以使用del指令進(jìn)行主動(dòng)刪除,可以使用expire指令設(shè)置過期時(shí)間,到點(diǎn)會自動(dòng)刪除,這屬于被動(dòng)刪除??梢允褂胻tl指令獲取字符串的壽命。

>?expire?ireader?60?(integer)?1??#?1表示設(shè)置成功,0表示變量ireader不存在?>?ttl?ireader?(integer)?50??#?還有50秒的壽命,返回-2表示變量不存在,-1表示沒有設(shè)置過期時(shí)間?>?del?ireader?(integer)?1??#?刪除成功返回1?>?get?ireader?(nil)??#?變量ireader沒有了?復(fù)制代碼

list

?Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程

Redis將列表數(shù)據(jù)結(jié)構(gòu)命名為list而不是array,是因?yàn)榱斜淼拇鎯Y(jié)構(gòu)用的是鏈表而不是數(shù)組,而且鏈表還是雙向鏈表。因?yàn)樗擎湵?,所以隨機(jī)定位性能較弱,首尾插入刪除性能較優(yōu)。如果list的列表長度很長,使用時(shí)我們一定要關(guān)注鏈表相關(guān)操作的時(shí)間復(fù)雜度。

負(fù)下標(biāo)?鏈表元素的位置使用自然數(shù)0,1,2,....n-1表示,還可以使用負(fù)數(shù)-1,-2,...-n來表示,-1表示「倒數(shù)第一」,-2表示「倒數(shù)第二」,那么-n就表示第一個(gè)元素,對應(yīng)的下標(biāo)為0。

隊(duì)列/堆棧?鏈表可以從表頭和表尾追加和移除元素,結(jié)合使用rpush/rpop/lpush/lpop四條指令,可以將鏈表作為隊(duì)列或堆棧使用,左向右向進(jìn)行都可以

#?右進(jìn)左出?>?rpush?ireader?go?(integer)?1?>?rpush?ireader?java?python?(integer)?3?>?lpop?ireader?"go"?>?lpop?ireader?"java"?>?lpop?ireader?"python"?#?左進(jìn)右出?>?lpush?ireader?go?java?python?(integer)?3?>?rpop?ireader?"go"?...?#?右進(jìn)右出?>?rpush?ireader?go?java?python?(integer)?3?>?rpop?ireader??"python"?...?#?左進(jìn)左出?>?lpush?ireader?go?java?python?(integer)?3?>?lpop?ireader?"python"?...?復(fù)制代碼

在日常應(yīng)用中,列表常用來作為異步隊(duì)列來使用。

長度?使用llen指令獲取鏈表長度

>?rpush?ireader?go?java?python?(integer)?3?>?llen?ireader?(integer)?3?復(fù)制代碼

隨機(jī)讀?可以使用lindex指令訪問指定位置的元素,使用lrange指令來獲取鏈表子元素列表,提供start和end下標(biāo)參數(shù)

>?rpush?ireader?go?java?python?(integer)?3?>?lindex?ireader?1?"java"?>?lrange?ireader?0?2?1)?"go"?2)?"java"?3)?"python"?>?lrange?ireader?0?-1??#?-1表示倒數(shù)第一?1)?"go"?2)?"java"?3)?"python"?復(fù)制代碼

使用lrange獲取全部元素時(shí),需要提供end_index,如果沒有負(fù)下標(biāo),就需要首先通過llen指令獲取長度,才可以得出end_index的值,有了負(fù)下標(biāo),使用-1代替end_index就可以達(dá)到相同的效果。

修改元素?使用lset指令在指定位置修改元素。

>?rpush?ireader?go?java?python?(integer)?3?>?lset?ireader?1?javascript?OK?>?lrange?ireader?0?-1?1)?"go"?2)?"javascript"?3)?"python"?復(fù)制代碼

插入元素?使用linsert指令在列表的中間位置插入元素,有經(jīng)驗(yàn)的程序員都知道在插入元素時(shí),我們經(jīng)常搞不清楚是在指定位置的前面插入還是后面插入,所以antirez在linsert指令里增加了方向參數(shù)before/after來顯示指示前置和后置插入。不過讓人意想不到的是linsert指令并不是通過指定位置來插入,而是通過指定具體的值。這是因?yàn)樵诜植际江h(huán)境下,列表的元素總是頻繁變動(dòng)的,意味著上一時(shí)刻計(jì)算的元素下標(biāo)在下一時(shí)刻可能就不是你所期望的下標(biāo)了。

>?rpush?ireader?go?java?python?(integer)?3?>?linsert?ireader?before?java?ruby?(integer)?4?>?lrange?ireader?0?-1?1)?"go"?2)?"ruby"?3)?"java"?4)?"python"?復(fù)制代碼

到目前位置,我還沒有在實(shí)際應(yīng)用中發(fā)現(xiàn)插入指定的應(yīng)用場景。

刪除元素?列表的刪除操作也不是通過指定下標(biāo)來確定元素的,你需要指定刪除的大個(gè)數(shù)以及元素的值

>?rpush?ireader?go?java?python?(integer)?3?>?lrem?ireader?1?java?(integer)?1?>?lrange?ireader?0?-1?1)?"go"?2)?"python"?復(fù)制代碼

定長列表?在實(shí)際應(yīng)用場景中,我們有時(shí)候會遇到「定長列表」的需求。比如要以走馬燈的形式實(shí)時(shí)顯示中獎(jiǎng)用戶名列表,因?yàn)橹歇?jiǎng)用戶實(shí)在太多,能顯示的數(shù)量一般不超過100條,那么這里就會使用到定長列表。維持定長列表的指令是ltrim,需要提供兩個(gè)參數(shù)start和end,表示需要保留列表的下標(biāo)范圍,范圍之外的所有元素都將被移除。

>?rpush?ireader?go?java?python?javascript?ruby?erlang?rust?cpp?(integer)?8?>?ltrim?ireader?-3?-1?OK?>?lrange?ireader?0?-1?1)?"erlang"?2)?"rust"?3)?"cpp"?復(fù)制代碼

如果指定參數(shù)的end對應(yīng)的真實(shí)下標(biāo)小于start,其效果等價(jià)于del指令,因?yàn)檫@樣的參數(shù)表示需要需要保留列表元素的下標(biāo)范圍為空。

快速列表

?Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程如果再深入一點(diǎn),你會發(fā)現(xiàn)Redis底層存儲的還不是一個(gè)簡單的linkedlist,而是稱之為快速鏈表quicklist的一個(gè)結(jié)構(gòu)。首先在列表元素較少的情況下會使用一塊連續(xù)的內(nèi)存存儲,這個(gè)結(jié)構(gòu)是ziplist,也即是壓縮列表。它將所有的元素緊挨著一起存儲,分配的是一塊連續(xù)的內(nèi)存。當(dāng)數(shù)據(jù)量比較多的時(shí)候才會改成quicklist。因?yàn)槠胀ǖ逆湵硇枰母郊又羔樋臻g太大,會比較浪費(fèi)空間。比如這個(gè)列表里存的只是int類型的數(shù)據(jù),結(jié)構(gòu)上還需要兩個(gè)額外的指針prev和next。所以Redis將鏈表和ziplist結(jié)合起來組成了quicklist。也就是將多個(gè)ziplist使用雙向指針串起來使用。這樣既滿足了快速的插入刪除性能,又不會出現(xiàn)太大的空間冗余。

hash

?Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程

哈希等價(jià)于Java語言的HashMap或者是Python語言的dict,在實(shí)現(xiàn)結(jié)構(gòu)上它使用二維結(jié)構(gòu),第一維是數(shù)組,第二維是鏈表,hash的內(nèi)容key和value存放在鏈表中,數(shù)組里存放的是鏈表的頭指針。通過key查找元素時(shí),先計(jì)算key的hashcode,然后用hashcode對數(shù)組的長度進(jìn)行取模定位到鏈表的表頭,再對鏈表進(jìn)行遍歷獲取到相應(yīng)的value值,鏈表的作用就是用來將產(chǎn)生了「hash碰撞」的元素串起來。Java語言開發(fā)者會感到非常熟悉,因?yàn)檫@樣的結(jié)構(gòu)和HashMap是沒有區(qū)別的。哈希的第一維數(shù)組的長度也是2^n。

?Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程

增加元素?可以使用hset一次增加一個(gè)鍵值對,也可以使用hmset一次增加多個(gè)鍵值對

>?hset?ireader?go?fast?(integer)?1?>?hmset?ireader?java?fast?python?slow?OK?復(fù)制代碼

獲取元素?可以通過hget定位具體key對應(yīng)的value,可以通過hmget獲取多個(gè)key對應(yīng)的value,可以使用hgetall獲取所有的鍵值對,可以使用hkeys和hvals分別獲取所有的key列表和value列表。這些操作和Java語言的Map接口是類似的。

>?hmset?ireader?go?fast?java?fast?python?slow?OK?>?hget?ireader?go?"fast"?>?hmget?ireader?go?python?1)?"fast"?2)?"slow"?>?hgetall?ireader?1)?"go"?2)?"fast"?3)?"java"?4)?"fast"?5)?"python"?6)?"slow"?>?hkeys?ireader?1)?"go"?2)?"java"?3)?"python"?>?hvals?ireader?1)?"fast"?2)?"fast"?3)?"slow"?復(fù)制代碼

刪除元素?可以使用hdel刪除指定key,hdel支持同時(shí)刪除多個(gè)key

>?hmset?ireader?go?fast?java?fast?python?slow?OK?>?hdel?ireader?go?(integer)?1?>?hdel?ireader?java?python?(integer)?2?復(fù)制代碼

判斷元素是否存在?通常我們使用hget獲得key對應(yīng)的value是否為空就直到對應(yīng)的元素是否存在了,不過如果value的字符串長度特別大,通過這種方式來判斷元素存在與否就略顯浪費(fèi),這時(shí)可以使用hexists指令。

>?hmset?ireader?go?fast?java?fast?python?slow?OK?>?hexists?ireader?go?(integer)?1?復(fù)制代碼

計(jì)數(shù)器?hash結(jié)構(gòu)還可以當(dāng)成計(jì)數(shù)器來使用,對于內(nèi)部的每一個(gè)key都可以作為獨(dú)立的計(jì)數(shù)器。如果value值不是整數(shù),調(diào)用hincrby指令會出錯(cuò)。

>?hincrby?ireader?go?1?(integer)?1?>?hincrby?ireader?python?4?(integer)?4?>?hincrby?ireader?java?4?(integer)?4?>?hgetall?ireader?1)?"go"?2)?"1"?3)?"python"?4)?"4"?5)?"java"?6)?"4"?>?hset?ireader?rust?good?(integer)?1?>?hincrby?ireader?rust?1?(error)?ERR?hash?value?is?not?an?integer?復(fù)制代碼

擴(kuò)容?當(dāng)hash內(nèi)部的元素比較擁擠時(shí)(hash碰撞比較頻繁),就需要進(jìn)行擴(kuò)容。擴(kuò)容需要申請新的兩倍大小的數(shù)組,然后將所有的鍵值對重新分配到新的數(shù)組下標(biāo)對應(yīng)的鏈表中(rehash)。如果hash結(jié)構(gòu)很大,比如有上百萬個(gè)鍵值對,那么一次完整rehash的過程就會耗時(shí)很長。這對于單線程的Redis里來說有點(diǎn)壓力山大。所以Redis采用了漸進(jìn)式rehash的方案。它會同時(shí)保留兩個(gè)新舊hash結(jié)構(gòu),在后續(xù)的定時(shí)任務(wù)以及hash結(jié)構(gòu)的讀寫指令中將舊結(jié)構(gòu)的元素逐漸遷移到新的結(jié)構(gòu)中。這樣就可以避免因擴(kuò)容導(dǎo)致的線程卡頓現(xiàn)象。

縮容?Redis的hash結(jié)構(gòu)不但有擴(kuò)容還有縮容,從這一點(diǎn)出發(fā),它要比Java的HashMap要厲害一些,Java的HashMap只有擴(kuò)容。縮容的原理和擴(kuò)容是一致的,只不過新的數(shù)組大小要比舊數(shù)組小一倍。

set

Java程序員都知道HashSet的內(nèi)部實(shí)現(xiàn)使用的是HashMap,只不過所有的value都指向同一個(gè)對象。Redis的set結(jié)構(gòu)也是一樣,它的內(nèi)部也使用hash結(jié)構(gòu),所有的value都指向同一個(gè)內(nèi)部值。

增加元素?可以一次增加多個(gè)元素

>?sadd?ireader?go?java?python?(integer)?3?復(fù)制代碼

讀取元素?使用smembers列出所有元素,使用scard獲取集合長度,使用srandmember獲取隨機(jī)count個(gè)元素,如果不提供count參數(shù),默認(rèn)為1

>?sadd?ireader?go?java?python?(integer)?3?>?smembers?ireader?1)?"java"?2)?"python"?3)?"go"?>?scard?ireader?(integer)?3?>?srandmember?ireader?"java"?復(fù)制代碼

刪除元素?使用srem刪除一到多個(gè)元素,使用spop刪除隨機(jī)一個(gè)元素

>?sadd?ireader?go?java?python?rust?erlang?(integer)?5?>?srem?ireader?go?java?(integer)?2?>?spop?ireader?"erlang"?復(fù)制代碼

判斷元素是否存在?使用sismember指令,只能接收單個(gè)元素

>?sadd?ireader?go?java?python?rust?erlang?(integer)?5?>?sismember?ireader?rust?(integer)?1?>?sismember?ireader?javascript?(integer)?0?復(fù)制代碼

sortedset

?Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程

SortedSet(zset)是Redis提供的一個(gè)非常特別的數(shù)據(jù)結(jié)構(gòu),一方面它等價(jià)于Java的數(shù)據(jù)結(jié)構(gòu)Map,可以給每一個(gè)元素value賦予一個(gè)權(quán)重score,另一方面它又類似于TreeSet,內(nèi)部的元素會按照權(quán)重score進(jìn)行排序,可以得到每個(gè)元素的名次,還可以通過score的范圍來獲取元素的列表。

zset底層實(shí)現(xiàn)使用了兩個(gè)數(shù)據(jù)結(jié)構(gòu),第一個(gè)是hash,第二個(gè)是跳躍列表,hash的作用就是關(guān)聯(lián)元素value和權(quán)重score,保障元素value的唯一性,可以通過元素value找到相應(yīng)的score值。跳躍列表的目的在于給元素value排序,根據(jù)score的范圍獲取元素列表。

增加元素?通過zadd指令可以增加一到多個(gè)value/score對,score放在前面

>?zadd?ireader?4.0?python?(integer)?1?>?zadd?ireader?4.0?java?1.0?go?(integer)?2?復(fù)制代碼

長度?通過指令zcard可以得到zset的元素個(gè)數(shù)

>?zcard?ireader?(integer)?3?復(fù)制代碼

刪除元素?通過指令zrem可以刪除zset中的元素,可以一次刪除多個(gè)

>?zrem?ireader?go?python?(integer)?2?復(fù)制代碼

計(jì)數(shù)器?同hash結(jié)構(gòu)一樣,zset也可以作為計(jì)數(shù)器使用。

>?zadd?ireader?4.0?python?4.0?java?1.0?go?(integer)?3?>?zincrby?ireader?1.0?python?"5"?復(fù)制代碼

獲取排名和分?jǐn)?shù)?通過zscore指令獲取指定元素的權(quán)重,通過zrank指令獲取指定元素的正向排名,通過zrevrank指令獲取指定元素的反向排名[倒數(shù)第一名]。正向是由小到大,負(fù)向是由大到小。

>?zscore?ireader?python?"5"?>?zrank?ireader?go??#?分?jǐn)?shù)低的排名考前,rank值小?(integer)?0?>?zrank?ireader?java?(integer)?1?>?zrank?ireader?python?(integer)?2?>?zrevrank?ireader?python?(integer)?0?復(fù)制代碼

根據(jù)排名范圍獲取元素列表?通過zrange指令指定排名范圍參數(shù)獲取對應(yīng)的元素列表,攜帶withscores參數(shù)可以一并獲取元素的權(quán)重。通過zrevrange指令按負(fù)向排名獲取元素列表[倒數(shù)]。正向是由小到大,負(fù)向是由大到小。

>?zrange?ireader?0?-1??#?獲取所有元素?1)?"go"?2)?"java"?3)?"python"?>?zrange?ireader?0?-1?withscores?1)?"go"?2)?"1"?3)?"java"?4)?"4"?5)?"python"?6)?"5"?>?zrevrange?ireader?0?-1?withscores?1)?"python"?2)?"5"?3)?"java"?4)?"4"?5)?"go"?6)?"1"?復(fù)制代碼

根據(jù)score范圍獲取列表?通過zrangebyscore指令指定score范圍獲取對應(yīng)的元素列表。通過zrevrangebyscore指令獲取倒排元素列表。正向是由小到大,負(fù)向是由大到小。參數(shù)-inf表示負(fù)無窮,+inf表示正無窮。

>?zrangebyscore?ireader?0?5?1)?"go"?2)?"java"?3)?"python"?>?zrangebyscore?ireader?-inf?+inf?withscores?1)?"go"?2)?"1"?3)?"java"?4)?"4"?5)?"python"?6)?"5"?>?zrevrangebyscore?ireader?+inf?-inf?withscores??#?注意正負(fù)反過來了?1)?"python"?2)?"5"?3)?"java"?4)?"4"?5)?"go"?6)?"1"?復(fù)制代碼

根據(jù)范圍移除元素列表?可以通過排名范圍,也可以通過score范圍來一次性移除多個(gè)元素

>?zremrangebyrank?ireader?0?1?(integer)?2??#?刪掉了2個(gè)元素?>?zadd?ireader?4.0?java?1.0?go?(integer)?2?>?zremrangebyscore?ireader?-inf?4?(integer)?2?>?zrange?ireader?0?-1?1)?"python"?復(fù)制代碼

跳躍列表?zset內(nèi)部的排序功能是通過「跳躍列表」數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)的,它的結(jié)構(gòu)非常特殊,也比較復(fù)雜。這一塊的內(nèi)容深度讀者要有心理準(zhǔn)備。

因?yàn)閦set要支持隨機(jī)的插入和刪除,所以它不好使用數(shù)組來表示。我們先看一個(gè)普通的鏈表結(jié)構(gòu)。

?Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程

我們需要這個(gè)鏈表按照score值進(jìn)行排序。這意味著當(dāng)有新元素需要插入時(shí),需要定位到特定位置的插入點(diǎn),這樣才可以繼續(xù)保證鏈表是有序的。通常我們會通過二分查找來找到插入點(diǎn),但是二分查找的對象必須是數(shù)組,只有數(shù)組才可以支持快速位置定位,鏈表做不到,那該怎么辦?

想想一個(gè)創(chuàng)業(yè)公司,剛開始只有幾個(gè)人,團(tuán)隊(duì)成員之間人人平等,都是聯(lián)合創(chuàng)始人。隨著公司的成長,人數(shù)漸漸變多,團(tuán)隊(duì)溝通成本隨之增加。這時(shí)候就會引入組長制,對團(tuán)隊(duì)進(jìn)行劃分。每個(gè)團(tuán)隊(duì)會有一個(gè)組長。開會的時(shí)候分團(tuán)隊(duì)進(jìn)行,多個(gè)組長之間還會有自己的會議安排。公司規(guī)模進(jìn)一步擴(kuò)展,需要再增加一個(gè)層級——部門,每個(gè)部門會從組長列表中推選出一個(gè)代表來作為部長。部長們之間還會有自己的高層會議安排。

跳躍列表就是類似于這種層級制,最下面一層所有的元素都會串起來。然后每隔幾個(gè)元素挑選出一個(gè)代表來,再將這幾個(gè)代表使用另外一級指針串起來。然后在這些代表里再挑出二級代表,再串起來。最終就形成了金字塔結(jié)構(gòu)。

想想你老家在世界地圖中的位置:亞洲-->中國->安徽省->安慶市->樅陽縣->湯溝鎮(zhèn)->田間村->xxxx號,也是這樣一個(gè)類似的結(jié)構(gòu)。

?Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程

「跳躍列表」之所以「跳躍」,是因?yàn)閮?nèi)部的元素可能「身兼數(shù)職」,比如上圖中間的這個(gè)元素,同時(shí)處于L0、L1和L2層,可以快速在不同層次之間進(jìn)行「跳躍」。

定位插入點(diǎn)時(shí),先在頂層進(jìn)行定位,然后下潛到下一級定位,一直下潛到最底層找到合適的位置,將新元素插進(jìn)去。你也許會問那新插入的元素如何才有機(jī)會「身兼數(shù)職」呢?

跳躍列表采取一個(gè)隨機(jī)策略來決定新元素可以兼職到第幾層,首先L0層肯定是100%了,L1層只有50%的概率,L2層只有25%的概率,L3層只有12.5%的概率,一直隨機(jī)到最頂層L31層。絕大多數(shù)元素都過不了幾層,只有極少數(shù)元素可以深入到頂層。列表中的元素越多,能夠深入的層次就越深,能進(jìn)入到頂層的概率就會越大。

創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開啟,新人活動(dòng)云服務(wù)器買多久送多久。


網(wǎng)頁標(biāo)題:?Redis數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)教程-創(chuàng)新互聯(lián)
當(dāng)前URL:http://weahome.cn/article/dpjhhj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部