溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

redis數(shù)據(jù)結(jié)構(gòu)有哪些內(nèi)容

發(fā)布時間:2021-12-23 09:35:07 來源:億速云 閱讀:152 作者:iii 欄目:數(shù)據(jù)庫

本篇內(nèi)容主要講解“redis數(shù)據(jù)結(jié)構(gòu)有哪些內(nèi)容”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“redis數(shù)據(jù)結(jié)構(gòu)有哪些內(nèi)容”吧!

redis不只是一個簡單的鍵(key)-值(value)數(shù)據(jù)庫,實際上它是一個數(shù)據(jù)結(jié)構(gòu)服務(wù)器,支持各種類型的值。也就是說,在傳統(tǒng)的鍵-值數(shù)據(jù)庫中,你把字符串鍵與字符串值聯(lián)系起來,而在redis,值不僅限于一個簡單的字符串,還可以是更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。下面列出了所有redis支持的數(shù)據(jù)結(jié)構(gòu),下文會分別對這些結(jié)構(gòu)進(jìn)行介紹:

  • 二進(jìn)制安全字符串

  • 隊列(lists):基于插入順序有序存儲的字符串元素集合。主要是鏈?zhǔn)降膌ist。

  • 集(sets):元素唯一的、無序的字符串元素集合。

  • 有序集(sorted sets):與sets相似,但是每個字符串元素都與一個被稱為分?jǐn)?shù)(score)的浮點數(shù)相關(guān)聯(lián)。和sets不同的是,元素能夠基于分?jǐn)?shù)排序,因此可以檢索某個范圍內(nèi)的元素(比如你可以查詢前10個或后10個)。

  • 哈希(hashes):由域(fields)和值之間關(guān)系組成的映射。域和值都是字符串。這和Ruby或Python的哈希非常相似。

  • 位數(shù)組(位圖bitmaps):可以通過特殊命令,像處理位圖一樣地處理字符串:設(shè)置和清除某一位,統(tǒng)計被置1的位數(shù),找到第一個被設(shè)置或沒有被設(shè)置的位等。

  • HyperLogLogs:這是一種概率數(shù)據(jù)結(jié)構(gòu),用于估算集的勢。不要被嚇到了,沒那么難。本文將在下文中HyperLogLog章節(jié)介紹。

遇到問題的時候,理解數(shù)據(jù)結(jié)構(gòu)是怎么工作的以及怎么被使用的并不是那么微不足道的事情。因此,這篇文檔是一個關(guān)于Redis數(shù)據(jù)類型和它們常用模式的速成教材。 
這里所有的例子,我們都使用redis客戶端(redis-cli)。相對于redis服務(wù)器來說,這是一個簡單方便的命令行控制臺。

redis的鍵

redis的鍵是二進(jìn)制安全【1】的,也說是說,你可以使用任意的二進(jìn)制序列作為鍵,比如字符串”foo”或一個JPEG文件的內(nèi)容。 
空串也是一個有效的鍵。 
一些關(guān)于鍵的其它規(guī)則:

  • 太長的鍵不推薦。例如長度為1024字節(jié)的鍵并不好,不管是從內(nèi)存角度,還是從查詢鍵的角度。因為從數(shù)據(jù)集中查詢鍵需要多次的鍵匹配步驟。即使手邊的任務(wù)就是要判斷一個很大的值是否存在,采用某種手段對它做hash是個好主意,尤其是從內(nèi)存和帶寬的角度去考慮。

  • 太短的鍵通常也不推薦。如果你把鍵“user:1000:followers”寫成“u1000flw”可能會有點問題。因為前者可讀性更好,而只需要多花費一點點的空間。短的鍵顯然占的花費的空間會小一點,因此你需要找到平衡點。

  • 盡量堅持模式。例如”object-type:id”是推薦的,就像”user:1000”。點和短線常用于多個單詞的場景,比如”comment:1234:reply.to”或”comment:1234:reply-to”。

  • 鍵的大小不能超過512MB。

Redis中的字符串

Redis中的字符串類型是可以與鍵關(guān)聯(lián)的最簡單的類型。它中Memcached中唯一的數(shù)據(jù)類型,也是Redis新手最常用的類型。 
由于Redis的鍵都是字符串,那么把使用字符串為值,也就是字符串到字符串的映射。字符串?dāng)?shù)據(jù)類型可以用于許多場景,比如緩存HTML片段或頁面。 
讓我們用redis客戶端嘗試一些字符串類型的使用吧(本文所有的例子都在redis客戶端執(zhí)行)。

> set mykey somevalueOK> get mykey"somevalue"

正如你所看到的,GET和SET命令用于設(shè)置或獲取一個字符串值。需要注意的是,如果鍵已經(jīng)存在,SET會覆蓋它的值,即使與這個鍵相關(guān)聯(lián)的不是字符串類型的值。SET相當(dāng)于賦值。 
值可以是任意類型的字符串(包含二進(jìn)制數(shù)據(jù)),你也可以使用一個jpeg圖像。值在大小不能大于512MB。 
SET命令配上一些額外的參數(shù),可以實現(xiàn)一些有趣的功能。例如,我可以要求如果鍵已經(jīng)存在,SET就會失敗,或者相反,鍵已經(jīng)存在時SET才會成功。

> set mykey newval nx(nil)> set mykey newval xxOK

雖然字符串是最基礎(chǔ)的數(shù)據(jù)類型,你仍可以對它執(zhí)行一些有趣的操作,比如原子性的自增:

> set counter 100OK> incr counter(integer) 101> incr counter(integer) 102> incrby counter 50(integer) 152

INCR命令把字符串解析成一個整數(shù),然后+1,把得到的結(jié)果作為一個新值存進(jìn)去。還有其它相似的命令:INCRBY, DECR, DECRBY。從命令的實現(xiàn)原理上講,這幾個命令是相同的,只是有一點細(xì)微的差別。 
為什么說INCR是原子性的呢?因為即使是多個客戶端對同一個鍵使用INCR命令,也不會形成競爭條件。舉個例子,像這樣的情況是不會發(fā)生的:客戶端1讀取到鍵是10,客戶端2也讀到鍵值是10,它們同時對它執(zhí)行自增命令,最終得到的值是11。實際上,最終的得到的值是12,因為當(dāng)一個客戶端對鍵值做讀-自增-寫的過程中,其它的客戶是不能同時執(zhí)行這個過程的。 
有許多用于操作字符串的命令,例如GETSET命令,它給鍵設(shè)置一個新值,并返回舊值。比如你有一個系統(tǒng),每當(dāng)有一個新的訪問者登陸你的網(wǎng)站時,使用INCR對一個鍵值自增。你可能想要統(tǒng)計每個小時的信息,卻又不希望丟失每次自增操作。你可以使用GETSET命令,設(shè)置一個新值“0”,同時讀取舊值。 
redis支持通過一條命令同時設(shè)置或讀取多個鍵,這對于減少延時很有用。這就是MSET命令和MGET命令:

> mset a 10 b 20 c 30OK> mget a b c1) "10"
2) "20"
3) "30"

使用MGET時,redis返回包含多個值的數(shù)組。

更改或查詢鍵空間

【2】 
有些命令并沒有指定特定的類型,但在與鍵空間的交互有非常有用,因此可以用于任意類型的鍵。 
舉個例子,EXISTS命令返回1或者0,用于表示某個給定的鍵在數(shù)據(jù)庫中是否存在。DEL命令刪除鍵以及它對應(yīng)的值而不管是什么值。

> set mykey helloOK> exists mykey(integer) 1> del mykey(integer) 1> exists mykey(integer) 0

DEL返回1還是0取決于鍵是(鍵存在)否(鍵不存在)被刪除掉了。 
有許多鍵空間相關(guān)的命令,但以上這兩個命令和TYPE命令是最基本的。TYPE命令的作用是返回這個鍵的值的類型。

> set mykey xOK> type mykeystring> del mykey(integer) 1> type mykeynone

鍵的生命周期

在介紹更多更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)之間,我們先討論另一個與值類型無關(guān)的特性,那就是redis的期限(redis expires)。最基本的,你可以給鍵設(shè)置一個超時時間,就是這個鍵的生存周期。當(dāng)生存周期過去了,鍵會被自動銷毀,就好像被用戶執(zhí)行過DEL一樣。 
一些關(guān)于redis期限的快速信息:

  • 生存周期可以設(shè)置的時間單位從秒級到毫秒級。

  • 生存周期的時間精度都是1毫秒。

  • 關(guān)于生存周期的數(shù)據(jù)有多份且存在硬盤上,基于Redis服務(wù)器停止了,時間仍在流逝,這意味著redis存儲的是key到期的時間。

設(shè)置生存周期是件瑣碎的事情:

> set key some-valueOK> expire key 5(integer) 1> get key (immediately)"some-value"> get key (after some time)(nil)

鍵在兩次調(diào)用之間消失了,這是因為第二次調(diào)用的延遲了超過5秒的時間。在上面的例子中,我們使用EXPIRE命令設(shè)置生命周期(它也可以用于為一個已經(jīng)設(shè)置過生命周期的鍵重新設(shè)置生命周期,PERSIST命令可以用于移除鍵的命令周期,使它能夠長期存在)。我們還可以使用redis命令在創(chuàng)建鍵的同時設(shè)置生命周期。比如使用帶參數(shù)的SET命令:

> set key 100 ex 10OK> ttl key(integer) 9

上面這個例子中創(chuàng)建了一個鍵,它的值是字符串100,生命周期是10秒。后面的TTL命令用于查看鍵的剩余時間。 
如果要以毫秒為單位設(shè)置或查詢鍵的生命周期,請查詢PEXPIRE命令和PTTL命令,以及SET命令的參數(shù)列表。

redis中的列表(lists)

要解釋列表數(shù)據(jù)類型,最好先從一點理論開始。因為列表這個術(shù)語常被信息技術(shù)人員錯誤地使用。例如“python 列表”,并不像它的命令所提示的(鏈表),而是數(shù)組(實際上與Ruby中的數(shù)組是同一個數(shù)據(jù)類型)。 
從廣義上講,列表只是元素的有序序列:10,20,1,2,3是一個列表。但是用數(shù)組實現(xiàn)的列表和用鏈表實現(xiàn)的列表,它們的屬性有很大的不同。 
redis的列表都是用鏈表的方式實現(xiàn)的。也就是說,即使列表中有數(shù)百萬個元素,增加一個新元素到列表頭部或尾部操作的執(zhí)行時間是常數(shù)時間。使用LPUSH命令把一個新元素增加到一個擁有10個元素的列表的頭部,或是增加到一個擁有一千萬個元素的列表的頭部,其速度是一樣的。 
缺點是什么呢?通過索引訪問一個元素的操作,在數(shù)組實現(xiàn)的列表中非常快(常數(shù)時間),但在鏈表實現(xiàn)的列表中不是那么快(與找到元素對應(yīng)下標(biāo)的速度成比例)。 
redis選擇用鏈表實現(xiàn)列表,因為對于一個數(shù)據(jù)庫來說,快速地向一個很大的列表新增元素是非常重要的。另一個使用鏈表的強大優(yōu)勢,你稍后將會看到,能夠在常數(shù)時間內(nèi)得到一個固定長度的redis列表。 
快速地讀取很大一堆元素的中間元素也是重要的,這時可以使用另一種數(shù)據(jù)結(jié)構(gòu),稱為有序集(sorted sets)。本文后面會講到有序集。

regis列表第一步

LPUSH命令把一個新的元素加到列表的左邊(頭部),而RPUSH命令把一個新的元素加到列表的右邊(尾部)。LRANGE命令從列表中提取某個范圍內(nèi)的元素

> rpush mylist A(integer) 1> rpush mylist B(integer) 2> lpush mylist first(integer) 3> lrange mylist 0 -11) "first"
2) "A"
3) "B"

注意,LRANGE命令需要輸入兩個下標(biāo),即范圍的第一個元素下標(biāo)和最后一個元素下標(biāo)。兩個下標(biāo)都可以是負(fù)的,意思是從尾部開始數(shù):因此-1是最后一個元素,-2是倒數(shù)第二個元素,等。 
正如你所見,RPUSH把元素加到列表右邊,LPUSH把元素加到列表左邊。所有命令的參數(shù)都是可變的,即你可以隨意地把多個增加元素入列表的命令放到一次調(diào)用中:

> rpush mylist 1 2 3 4 5 "foo bar"(integer) 9
> lrange mylist 0 -1
1) "first"2) "A"3) "B"4) "1"5) "2"6) "3"7) "4"8) "5"9) "foo bar"

Redis中定義了一個重要的操作就是刪除元素。刪除命令可以同時從列表中檢索和刪除元素。你可以從左邊或者右邊刪除元素,和從兩邊增加元素的方法類似:

> rpush mylist a b c(integer) 3> rpop mylist"c"> rpop mylist"b"> rpop mylist"a"

我們增加和刪除的三個元素,因此最后列表是空的,沒有元素可以刪除。如果我們嘗試?yán)^續(xù)刪除元素,會得到這樣的結(jié)果:

> rpop mylist(nil)

redis返回空值說明列表中沒有元素了。

列表的常見用例

列表可以用于完成多種任務(wù),以下是兩個非常有代表性的用例:

  • 記住用戶發(fā)布到社交網(wǎng)絡(luò)的最新更新。

  • 使用消費者-生產(chǎn)者模型進(jìn)行進(jìn)程間通信,生產(chǎn)生把表項(items)放進(jìn)列表中,消費者(通常是工作者)消費這些items并執(zhí)行一些行為。redis針對這種用例有一些特殊的列表命令,既可靠又高效。

例如非常有名的Ruby庫resque和sidekip,在底層都使用了Redis列表來實現(xiàn)后臺作業(yè)。 
著名的社交網(wǎng)絡(luò)Twitter使用Redis列表來獲取用戶發(fā)布的最新的消息。 
為了一步一步地描述一個常見用例,假設(shè)要在你的主頁上展示社交網(wǎng)絡(luò)上最新分享的照片并且加速訪問。

  • 每當(dāng)一個用戶發(fā)布了一張新的照片,我們使用LPUSH命令把它的ID加入到列表中。

  • 當(dāng)用戶訪問這個主頁,我們使用LRANGE 0 9獲取最新加入的10個表項。

限制列表

很多情況下我們只想要使用列表來存儲最新的幾條表項,例如社交網(wǎng)絡(luò)更新、日志或者其它。 
Redis允許我們使用列表作為一個固定集合,使用LTRIM命令,只記錄最新的N條記錄,而丟棄所有更早的記錄。 
LTRIM命令和LRANGE命令相似,但不像LRANGE一樣顯示特定范圍的元素,而是用這個范圍內(nèi)的值重新設(shè)置列表。所有范圍外的元素都被刪除了。 
用個例子來說明這一點:

> rpush mylist 1 2 3 4 5(integer) 5> ltrim mylist 0 2OK> lrange mylist 0 -11) "1"
2) "2"
3) "3"

上面的LTRIM命令告訴Redis只取得列表中下標(biāo)為0到2的元素,其它的都要丟棄。這就是一種簡單有用的模式成為了可能:列表增加(push)元素操作+列表提取(trim)元素操作=增加一個元素同時刪除一個元素使得列表元素總數(shù)有限:

LPUSH mylist <some element>LTRIM mylist 0 999

上面的操作結(jié)合增加一個元素但只是存在1000個最新的元素在列表中。通過LRANGE你可以獲取最新的表項而不需要記住舊的數(shù)據(jù)。 
注意:由于理論上LRANGE是O(N)命令,讀取從頭開始或從尾開始的小范圍數(shù)據(jù)是常數(shù)時間的操作。

列表中是阻塞型操作

列表的一些特性使它適合現(xiàn)實隊列(queues),也通常作為進(jìn)程間通信系統(tǒng)的一個基礎(chǔ)組件:阻塞式操作。 
假設(shè)你通過一個進(jìn)程把元素增加到列表中,使用另一個進(jìn)程對這些元素做些實際的操作。這是通常的生產(chǎn)者/消費者基礎(chǔ),你可以用下面這種簡單的方法實現(xiàn):

  • 生產(chǎn)者調(diào)用LPUSH,把元素加入列表

  • 消費者調(diào)用RPOP,把元素從列表中取出或處理

有沒有可能出現(xiàn)這種情況,列表是空的,沒有什么東西可以處理,因此RPOP返回NULL。這種情況下,消費者不得不等一會再嘗試RPOP。這就叫輪詢。這并不是一個好方法,因為它有以下缺點:

  1. 要求redis和客戶端執(zhí)行沒有意義的命令(當(dāng)列表為空是所有的請求都不會執(zhí)行實際工作,只是返回NULL)

  2. 工作者在收到NULL之后加入一個延時,讓它等待一些時間。如果讓延時小一點,在兩次調(diào)用RPOP之間的等待時間會比較短,這成為第一個問題的放大-調(diào)用Redis更加沒有意義

因此Redis實現(xiàn)了命令BRPOP和BLPOP,它是RPOP和LPOP的帶阻塞功能的版本:當(dāng)列表為空時,它們會等到一個新的元素加入到列表時,或者用戶定義的等待時間到了時,才會返回。 
這是BRPOP調(diào)用的一個例子,我們可以在工作者進(jìn)程使用它:

> brpop tasks 5
1) "tasks"2) "do_something"

它的意思是:等待列表中的元素,如果5秒還沒有可用的元素。 
注意,如果使用0作為超時時間,將會永遠(yuǎn)等待,你也可以定義多個列表而不只是一個,這樣就會同時等待多個列表,當(dāng)任意一個列表收到一個元素時就會收到通知。 
一些關(guān)于BRPOP需要注意的事情:

  1. 客戶端是按順序被服務(wù)的:第一個等待某個列表的客戶端,當(dāng)列表被另一個客戶端增加一個元素時,它會第一個處理。

  2. 返回值與RPOP的不同:只得到兩個元素的包含鍵名的數(shù)組,因為BRPOP和BLPOP因為等待多個列表而阻塞。

  3. 如果時間超時了,就會返回NULL

還有更多你應(yīng)該知道的關(guān)于列表和阻塞操作的東西。我們建議你閱讀以下材料:

  • 可以使用RPOPLPUSH創(chuàng)建更安全的隊列或旋轉(zhuǎn)隊列。

  • 這個命令有一個阻塞參數(shù),即BRPOPLPUSH

自動創(chuàng)建和移除鍵

到目前為止我們的例子還沒有涉及到這些情景,在增加一個元素之間創(chuàng)建一個空的列表,或者當(dāng)一個列表沒有元素時把它移除。redis有責(zé)任刪除變?yōu)榭盏牧斜恚虍?dāng)我們試圖增加元素時創(chuàng)建空列表。例如LPUSH 
這不僅適用于列表,它可以應(yīng)用于所有包含多個元素的Redis數(shù)據(jù)結(jié)構(gòu)-集、有序集和哈希。 
基本上講,我們把它的行為總結(jié)為三個規(guī)則:

  1. 當(dāng)我們把一個元素增加到一個集合類數(shù)據(jù)類型時,如果這個鍵不存在,在增加前會創(chuàng)建一個空的集合類數(shù)據(jù)類型。

  2. 我們從一個集合類數(shù)據(jù)類型中移除一個元素時,如果值保持為空,鍵就會被自動刪除

  3. 調(diào)用一個只讀命令例如LLEN(返回列表的長度),或者一個移除元素的寫命令但鍵為空,結(jié)果不會改變。[3]

規(guī)則1舉例:

> del mylist(integer) 1> lpush mylist 1 2 3(integer) 3

然而,我們不能對一個已經(jīng)存在的鍵執(zhí)行與它類型不同的操作:

> set foo barOK> lpush foo 1 2 3(error) WRONGTYPE Operation against a key holding the wrong kind of value> type foostring

規(guī)則2舉例:

> lpush mylist 1 2 3(integer) 3> exists mylist(integer) 1> lpop mylist"3"> lpop mylist"2"> lpop mylist"1"> exists mylist(integer) 0

當(dāng)所有元素被取出,這個鍵就不存在了。 
規(guī)則3舉例:

> del mylist(integer) 0> llen mylist(integer) 0> lpop mylist(nil)

redis中的哈希(hashed)

redis的哈希和我們所認(rèn)識的“哈?!狈浅O嗨疲怯?值對。

> hmset user:1000 username antirez birthyear 1977 verified 1
OK
> hget user:1000 username"antirez"> hget user:1000 birthyear"1977"> hgetall user:1000
1) "username"2) "antirez"3) "birthyear"4) "1977"5) "verified"6) "1"

hash表示對象(object)非常方便。實際上,可以放入一個hash的域的數(shù)量沒有限制(不考慮可用內(nèi)存),因此你可以在你的應(yīng)用中用許多不同的方式使用哈希。 
HMSET命令為hash設(shè)置多個域,而HGET獲取某一個域。HMGET和HGET相似,但它返回由值組成的數(shù)組。

> hmget user:1000 username birthyear no-such-field1) "antirez"2) "1977"3) (nil)

還有一些命令可以對單個的域執(zhí)行操作,例如HINCRBY:

> hincrby user:1000 birthyear 10(integer) 1987> hincrby user:1000 birthyear 10(integer) 1997

你可以查看這篇文檔《hash命令全列》 
把小的哈希(少量的元素,較小的值)用特殊的編碼方式存放在內(nèi)存中并不是什么難事,因此它們的空間效率非常高。

redis的集(sets)

Redis的集是字符串無序的集合。SADD向集中增加一些元素。對于集合還有很多其它的操作,例如測試某個給定的元素是否存在,多個集合之間求交集、合集或者差集,等。

> sadd myset 1 2 3(integer) 3> smembers myset1. 32. 13. 2

在這個例子中,我向myset中增加了三個元素,并讓redis返回所有的元素。正如你所看到的,它們是無序的。每次調(diào)用,redis都可能以任何順序返回元素,因此在這里,用戶不能對元素的順序有要求。 
redis提供測試成員的命令。這個給定的元素是否存在?

> sismember myset 3(integer) 1> sismember myset 30(integer) 0

“3”是這個集中的一員,而“30”不是。 
集善于表現(xiàn)對象之間的關(guān)系。例如我們可以很容易使用集實現(xiàn)標(biāo)簽(tags)。處理這個問題的一個簡單的模型就是把所有要打標(biāo)簽的對象設(shè)置一個集。集包含相關(guān)對象的標(biāo)簽的ID。 
假設(shè)我們想要為新聞加標(biāo)簽。ID為1000的新聞被打上1,2,5和77這幾個標(biāo)簽,我們可以用一個集將這些標(biāo)簽ID與新聞關(guān)聯(lián)起來:

> sadd news:1000:tags 1 2 5 77(integer) 4

然而有時我會想要相反的關(guān)系:列表中的所有新聞都被打上一個給定的標(biāo)簽:

> sadd tag:1:news 1000(integer) 1> sadd tag:2:news 1000(integer) 1> sadd tag:5:news 1000(integer) 1> sadd tag:77:news 1000(integer) 1

要獲取一個對象的所有標(biāo)簽是很麻煩的。

> smembers news:1000:tags1. 52. 13. 774. 2

注意:在這個例子中我們假設(shè)你還有另一個數(shù)據(jù)結(jié)構(gòu),例如redis的哈希,用于標(biāo)簽ID到標(biāo)簽名的映射。 
如果使用正確的redis命令,可以通過并不繁瑣卻簡單的方式去實現(xiàn)。例如我們可能想到同時擁有1,2,10和27標(biāo)簽的所有對象。我們可以使用SINTER命令執(zhí)行不同集之間的求交運算。我們可以這么用:

> sinter tag:1:news tag:2:news tag:10:news tag:27:news... results here ...

求交集運算不是唯一可以執(zhí)行的操作,你還可以執(zhí)行求并集運算、求差集運算、提取任意一個元素等。 
提取一個元素的命令是SOP,它對于模擬某些問題很方便。例如要實現(xiàn)一個基于網(wǎng)頁的撲克牌游戲,你可能會把你的牌(deck)做成一個集。假設(shè)我們使用一個字符前綴來表示C(梅花)、D(方塊)、H(紅心)、S(黑桃):

>  sadd deck C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 CJ CQ CK
   D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 DJ DQ DK H1 H2 H3
   H4 H5 H6 H7 H8 H9 H10 HJ HQ HK S1 S2 S3 S4 S5 S6
   S7 S8 S9 S10 SJ SQ SK
   (integer) 52

現(xiàn)在我們給每個玩家提供5張牌。SPOP命令移除一個隨機的元素,并把它返回給客戶端,因此在這個用例中是最好的操作。 
然后如果我們直接對deck調(diào)用它,下一輪游戲我們需要把再次填寫所有的牌,這還不夠理想。因此在開始之前,先把集中存儲的deck鍵做一個備份到game中。使用SUNIONSTORE來實現(xiàn),把結(jié)果存到另一個集中。這個命令通常是對多個集做求并集運行的。對一個集求并集運算就是它自己,因此可以用于復(fù)制:

> sunionstore game:1:deck deck(integer) 52

現(xiàn)在我已經(jīng)準(zhǔn)備好為第一個玩家發(fā)五張牌了。

> spop game:1:deck"C6"> spop game:1:deck"CQ"> spop game:1:deck"D1"> spop game:1:deck"CJ"> spop game:1:deck"SJ"

一對J,不太好。。。 
現(xiàn)在是時候介紹集中元素個數(shù)的命令了。在集理論中,元素個數(shù)常被為集的勢,因此這個命令是SCARD。

> scard game:1:deck(integer) 47

計算公式:52-5=47 
如果你只是想得到一個隨機的元素但不把它從集中刪除,SRANDMEMBER命令適合這個任務(wù)。它還可以提供返回重復(fù)元素或非重要元素的功能。

Redis的有序集

有序集像一種將集和哈?;旌系臄?shù)據(jù)類型。像集一樣,有序集由唯一的不重復(fù)的字符串元素組成。因此某種意義上說,有序集也是一個集。 
集中的元素是無序的,而有序集中的元素都基于一個相關(guān)聯(lián)的浮點值排序。這個浮點值稱為分?jǐn)?shù)(score)(每個元素都映射到一個值,因此和哈希相似)。 
此外,有序集中的元素是按順序取的(它們不是按照要求排序的,排序是這個數(shù)據(jù)結(jié)構(gòu)用于表現(xiàn)有序集的一個特性【4】)。它們按照下面的規(guī)則排序:

  • 假設(shè)A和B是分值不同的兩個元素,如果A的分?jǐn)?shù)>B的分?jǐn)?shù),則A>B

  • 假設(shè)A和B的分值相同,如果字符串A的字典序大于字符串B的字典序,則A>B。A和B兩個字符串不可能相同,因為有序集的元素是唯一的。

我們從一個簡單的例子開始,向有序集增加一些黑客的名字,將它們的出生年份作為“分?jǐn)?shù)”。

> zadd hackers 1940 "Alan Kay"(integer) 1> zadd hackers 1957 "Sophie Wilson"(integer 1)> zadd hackers 1953 "Richard Stallman"(integer) 1> zadd hackers 1949 "Anita Borg"(integer) 1> zadd hackers 1965 "Yukihiro Matsumoto"(integer) 1> zadd hackers 1914 "Hedy Lamarr"(integer) 1> zadd hackers 1916 "Claude Shannon"(integer) 1> zadd hackers 1969 "Linus Torvalds"(integer) 1> zadd hackers 1912 "Alan Turing"(integer) 1
  • 1

正如你所見,ZADD和SADD相似,但是需要一個額外的參數(shù)(位置在要加的元素之前),這就是分?jǐn)?shù)。ZADD也是參數(shù)可變的,你可以隨意地定義多個“分?jǐn)?shù)-值”對,雖然上面的例子沒有這么寫。 
要求有序集中的黑客名單按他們的出生年份排序是沒有意義的,因為它們已經(jīng)是這樣的了。 
實現(xiàn)細(xì)節(jié):有序集是基于一個雙端口數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的,包含一個跳躍表和一個哈希表。因此增加一個元素的執(zhí)行時間是O(log(N))。這很好,當(dāng)我們請求有序的元素時不需要其它的工作,它們已經(jīng)是排序的了:

> zrange hackers 0 -1
1) "Alan Turing"2) "Hedy Lamarr"3) "Claude Shannon"4) "Alan Kay"5) "Anita Borg"6) "Richard Stallman"7) "Sophie Wilson"8) "Yukihiro Matsumoto"9) "Linus Torvalds"

注意:0和-1的意思是從下標(biāo)為0的元素開始到最后一個元素(這里的-1和LRANGE命令中的-1一樣)。 
如果想要反向排序,從最年輕到最老呢?使用ZREVERANGE代替ZRANGE。

> zrevrange hackers 0 -1
1) "Linus Torvalds"2) "Yukihiro Matsumoto"3) "Sophie Wilson"4) "Richard Stallman"5) "Anita Borg"6) "Alan Kay"7) "Claude Shannon"8) "Hedy Lamarr"9) "Alan Turing"

也可以同時返回分?jǐn)?shù),使用WITHSCORES參數(shù):

> zrange hackers 0 -1 withscores
1) "Alan Turing"2) "1912"3) "Hedy Lamarr"4) "1914"5) "Claude Shannon"6) "1916"7) "Alan Kay"8) "1940"9) "Anita Borg"10) "1949"11) "Richard Stallman"12) "1953"13) "Sophie Wilson"14) "1957"15) "Yukihiro Matsumoto"16) "1965"17) "Linus Torvalds"18) "1969"

基于范圍的操作

有序集的功能強大遠(yuǎn)不止這些。它還可以基于范圍操作。我們要取得所有出生年份早于(包括)1950年的人,就使用ZRANGEBYSCORE命令來實現(xiàn):

> zrangebyscore hackers -inf 1950
1) "Alan Turing"2) "Hedy Lamarr"3) "Claude Shannon"4) "Alan Kay"5) "Anita Borg"

我們請求Redis返回所有分?jǐn)?shù)在無限到1950(兩邊都是閉區(qū)間)之間的元素。 
也可以移除某個范圍內(nèi)的元素。我們要從有序集中移除所有出生年份在1940和1960之間的黑客:

> zremrangebyscore hackers 1940 1960(integer) 4

ZREMRANGEBYSCORE命令的名字也許不是很好,但是真的很有用,它返回被移除的元素的個數(shù)。 
另一個為有序集元素定義的非常有用的操作是獲取排名(get-rank)操作。可以詢問一個元素在它的有序集中的位置。

> zrank hackers "Anita Borg"(integer) 4

ZREVRANK命令也可以獲取排名,不過元素是逆序排序的。

字典序的分?jǐn)?shù)

最近的Redis 2.8版本引入了一個新特性,假設(shè)有序集中所有元素的分?jǐn)?shù)相同(使用C語言的memcmp函數(shù)來比較元素,這樣保證每個redis實例都會返回相同的結(jié)果)的情況下,允許按照字典序獲得范圍?!?】 
針對字典序范圍操作的主要命令是ZRANGEBYLEX、ZREVRANGEBYLEX、ZREMRANGEBYLEX和ZLEXCOUNT。 
舉個例子,我們再次把所有著名黑客加入到列表中,但這一次所有元素的分?jǐn)?shù)都是0:

> zadd hackers 0 "Alan Kay" 0 "Sophie Wilson" 0 "Richard Stallman" 0  "Anita Borg" 0 "Yukihiro Matsumoto" 0 "Hedy Lamarr" 0 "Claude Shannon"
  0 "Linus Torvalds" 0 "Alan Turing"

基于有序集的排序規(guī)則,它們是字典序排序的:

> zrange hackers 0 -1
1) "Alan Kay"2) "Alan Turing"3) "Anita Borg"4) "Claude Shannon"5) "Hedy Lamarr"6) "Linus Torvalds"7) "Richard Stallman"8) "Sophie Wilson"9) "Yukihiro Matsumoto"

我們可以使用ZRANGEBYLEX命令請求字典序的范圍:

> zrangebylex hackers [B [P
1) "Claude Shannon"2) "Hedy Lamarr"3) "Linus Torvalds"

范圍是開區(qū)間還是閉區(qū)間都可以(由第一個字符決定),字符串正無窮和負(fù)無窮分別通過+和-來定義。更多信息請查看文檔。 
這個特性很重要,它使得我們使用有序集作為一個通常索引。舉個例子,如果你想要使用一個128位的無符號整數(shù)來為元素索引,你所要做的只是把元素加入到一個有序集并設(shè)置一個相同的分?jǐn)?shù)(比如0)以及一個由128位數(shù)值組成的8字節(jié)前綴。由于數(shù)值是大端的,字典序的順序(原始字節(jié)序)實際上是數(shù)字序的,你可以在128位空間請求范圍,以前綴降序返回元素的值。 
如果你想查看這個特性更嚴(yán)謹(jǐn)?shù)难菔?,請查?Redis autocomplete demo.

更新分?jǐn)?shù):排行榜

這是在切換到下一個話題之前最后一個關(guān)于有序集的點。有序集的分?jǐn)?shù)可以隨時被更新。只需要對一個在有序集中已經(jīng)存在的元素執(zhí)行ZADD就可以在O(log(N))更新它的分?jǐn)?shù)(和位置)。同樣的,當(dāng)會經(jīng)常更新時使用有序集非常合適。 
這個特性的一個通常用例是排行榜。典型的應(yīng)用是Facebook的一個游戲,你可以使用戶基于它們的高分排序,增加獲取排名的操作,在排行榜上顯示前N個用戶及用戶排名(例:你是第4932好的分?jǐn)?shù))

位圖

位圖其實不是一個真正的數(shù)據(jù)類型,只是在這種字符串類型上有一系列基于位的操作。由于字符串是二進(jìn)制安全的,最大長度是512MB,因此可以設(shè)置多達(dá)2^32種不同的位串。 
位操作分為兩類,一種是針對某一個位的常數(shù)時間操作,如果設(shè)置某個位為1或0,或獲取某個位的值。另一種是對所有位的操作,例如計算一個給定范圍內(nèi)被設(shè)置為1的位的個數(shù)(如人數(shù)統(tǒng)計)。 
位圖一個最大的優(yōu)勢就是存儲信息時非常少空間。例如一個系統(tǒng)里面每個用戶用一個不同的遞增的用戶ID表示,可以記錄40億用戶的某個信息(這個用戶是否想要接收郵件)只需要512M的內(nèi)存。 
通過SETBIT命令和GETBIT命令設(shè)置或獲取位:

> setbit key 10 1(integer) 1> getbit key 10(integer) 1> getbit key 11(integer) 0

SETBIT命令把第一個參數(shù)作為位的序號,第二個參數(shù)作為這個位要設(shè)置的值,只能是1或0。如果地址位大于當(dāng)前字符串的長度,這個命令會自動擴充字符串。 
GETBIT只返回位于某個位置的值。超過長度的位(地址位大于字符串的長度)將必然得到0。 
這三個命令是對所有位的操作:

  1. BITOP:執(zhí)行不同字符串之間的位操作。包括AND、OR、XOR和NOT。

  2. BITCOUNT:執(zhí)行統(tǒng)計操作,返回位集中1的個數(shù)

  3. BITPOS:找到第一個被設(shè)置為0或1的位置

BITPOS和BITCOUNT都可以接受位的地址范圍作為參數(shù),這樣就不對對整個字符串做操作。下面是一個關(guān)于BITCOUNT的簡單例子:

> setbit key 0 1(integer) 0> setbit key 100 1(integer) 0> bitcount key(integer) 2

位圖的通常用法:

  • 各種實時分析

  • 存儲要求空間時間高效的與對象ID關(guān)聯(lián)的二進(jìn)制信息。

假如你想知道你的網(wǎng)頁用戶中每天訪問最長的時間【6】,你從開始記錄天數(shù),你把你的網(wǎng)頁公開化的第一天開始,計數(shù)為0,然后每當(dāng)有用戶用戶網(wǎng)頁,使用SETBIT設(shè)置一位。位的下標(biāo)可以簡單的認(rèn)為是當(dāng)前系統(tǒng)時間,減去第一天得到偏移,然后除以3600*24。 
使用這種方式,對于每一個用戶,你有一個包含每天訪問信息的字符串來表示。使用BITCOUNT命令可以得到某個用戶訪問網(wǎng)頁的天數(shù)。而使用多個BITOPs調(diào)用,可能簡單地獲取和分析位圖,就很容易地計算出longest streak。 
為了共享數(shù)據(jù)或避免對一個很大的鍵操作,bitmap可以分裂成多個鍵。要把一個位圖分裂成多個鍵而不是全部設(shè)置到一個鍵里面去,一個比較麻煩的方法就是讓每個鍵存儲M位,鍵名為鍵的數(shù)量/M,第N個位在這個鍵里的地址是數(shù)的位置%M。

HyperLogLogs

HyperLogLogs是一個概率性的數(shù)據(jù)結(jié)構(gòu),用于計算特別的東西(技術(shù)上常用于估算一個集的勢)。通過計算一個特別的表項需要使用相對于要計算的表項本身來說很大的內(nèi)存,因為需要記住你已經(jīng)見過的元素,以免重復(fù)計算。然后有一系列算法可以按精度使用內(nèi)存:在redis的實現(xiàn)中,你最終得到一個標(biāo)準(zhǔn)錯誤的估計測量結(jié)果的可能性少于1%【7】。這個算法的神奇之處在于你再大需要相對于要計算的表項本身來說很大的內(nèi)存空間,可能是只使用一個常數(shù)數(shù)量的空間。最壞情況下12K字節(jié),如果元素少的話,這個空間會更小。 
Redis中的HLL,從技術(shù)上講,它是一個完全不同的數(shù)據(jù)結(jié)構(gòu),但像字符串一樣編碼,因此你可以使用GET來串行化一個HLL,使用SET并行到服務(wù)器。 
從概念上講,HLL的接口使用集來完成相同的工作。你會使用SADD把每一個觀測值寫入集中,使用SCARD來查詢集中的元素個數(shù)。因為SADD不會重復(fù)添加一個已存在的元素,因此集中的元素是唯一的。 
但是你不能把一個表項真正地添加入一個HLL,因為數(shù)據(jù)結(jié)構(gòu)只包含并不真正存在的元素的狀態(tài),API是一樣的:

  • 每當(dāng)你看見一個新的元素,使用PFADD計數(shù)增加

  • 每當(dāng)你想要恢復(fù)當(dāng)前的近似值,使用PFCOUNT。【8】

> pfadd hll a b c d(integer) 1> pfcount hll(integer) 4

使用這種數(shù)據(jù)結(jié)構(gòu)的一個例子統(tǒng)計在一個調(diào)整中用戶每天執(zhí)行的請求數(shù)。 
Redis還可以對HLL執(zhí)行求并集操作,請查詢完整文件獲取更多信息。

其它顯著的特性

關(guān)于redis的接口,還有其它一些重要的信息不能放在這個文檔中,但是非常值得引起你的注意:

  • 可以遞增地迭代鍵空間

  • 可以在服務(wù)器端運行LUA腳本獲取潛在因素和帶寬

  • redis還是一個發(fā)布-訂閱型服務(wù)器

REDIS所有的命令

<<ABOUT LIST>>

LPOP key :                    刪除并取得LIST頭部一個元素

RPOP key :                    刪除并取得LIST尾部一個元素

BLPOP key [key ...] timeout : 刪除并取得LIST頭部一個元素,如果沒有就BLOCK

BRPOP key [key ...] timeout : 刪除并取得LIST尾部一個元素,如果沒有就BLOCK

LPUSH key value :             在LIST頭部擴展一個元素

RPUSH key value :             在LIST尾部擴展一個元素

LPUSHX key value :            如果LIST存在,在LIST頭部擴展一個元素

RPUSHX key value :            如果LIST存在,在LIST尾部擴展一個元素

LINDEX key index :            通過INDEX取得LIST的一個元素

LLEN key :                    取得LIST的長度

LRANGE key start stop :       取得LIST在指定范圍內(nèi)的元素

LREM key count value :        刪除LIST的元素們

LSET key index value :        設(shè)置LIST索引為INDEX的元素的值

LTRIM key start stop :        裁剪LIST,保留一定范圍的元素

RPOPLPUSH source destination :刪除當(dāng)前LIST的尾部一個元素,并將其擴展到另一個LIST的尾部

BRPOPLPUSH source destination timeout :

                              彈出LIST一個元素,并將其插入到另一個LIST里,然后返回,如果前個LIST空就BLOCK

SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination] :

                              排序LIST,SET, SORTED SET

<<ABOUT SET>>

SADD key member :                       向SET中添加一個成員

SREM key member :                       從SET中刪除一個成員

SDIFF key [key ...] :                   集合求差集

SINTER key [key ...] :                  集合求交集

SUNION key [key ...] :                  集合求并集

SDIFFSTORE destination key [key ...] :  集合求差集,并保存結(jié)果集到另一集合

SINTERSTORE destination key [key ...] : 集合求交集,并保存結(jié)果集到另一集合

SUNIONSTORE destination key [key ...] : 集合求并集,并保存結(jié)果集到另一集合

SCARD key :                             取得SET成員總數(shù)

SISMEMBER key member :                  判斷給定值是否為SET成員

SPOP key :                              刪除并返回SET任一成員

SRANDMEMBER key :                       返回SET任一成員

SMEMBERS key :                          取得SET所有成員

SMOVE source destination member :       將一個SET中一個成員移動到另一個SET中

<<ABOUT SORTED SET>>

ZADD key score member :                 在SSET中添加一個成員,或者說更新已有成員的SCORE

ZCARD key :                             取得SSET的成員總數(shù)

ZCOUNT key min max :                    計算SSET中SCORE在一個給定范圍內(nèi)的成員總數(shù)

ZINCRBY key :                           為SSET中的成員自增SCORE

ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] :

                                        求SSET交集,并將結(jié)果集保存到一個新KEY

ZRANGE key start stop [WITHSCORES] :    返回SSET中一定INDEX范圍內(nèi)的成員

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] : 返回SSET中一定SCORE范圍內(nèi)的成員

ZREM key member :                       刪除SSET中一個成員

ZREMRANGEBYRANK key start stop :        刪除SSET一定INDEX范圍內(nèi)的成員

ZREMRANGEBYSCORE key min max :          刪除SSET一定SCORE范圍內(nèi)的成員

ZREVRANGE key start stop [WITHSCORES] : 返回SSET中一定INDEX范圍內(nèi)的成員,其順序是SCORE從高到低

ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] : 返回SSET中一定SCORE范圍內(nèi)的成員,其順序是SCORE從高到低

ZSCORE key member :                     獲得SSET中與給定MEMBER關(guān)聯(lián)的SCORE

ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] :

                                        SSET求并集,并將結(jié)果集存到一個新的KEY中

<<ABOUT HASH>>

HDEL key field :                            刪除一個HASHFIELD

HEXISTS key field :                         判斷一個HASHFIELD是否存在

HGET key field :                            獲得一個HASHFIELD的值

HGETALL key :                               獲得一個HASH所有的FIELDs和VALUEs

HINCRBY key field increment :               對HASHFIELD的整數(shù)值增加increment的整數(shù)值

HKEYS key :                                 獲得HASH所有的FIELD

HLEN key :                                  獲得HASH內(nèi)FIELD總數(shù)

HMGET key field [field ...] :               獲得HASH指定FIELD的所有值

HMSET key field value [field value ...] :   設(shè)置HASH的一些FILED和VALUE

HSET key field value :                      設(shè)置HASH的某FIELD為某值

HSETNX key field value :                    當(dāng)HASH的某FIELD不存在時候,設(shè)置其為某值

HVALS key :                                 獲得HASH的所有值

<<ABOUT KEY>>

DEL key [key ...] :         刪除一個KEY

GET key :                   獲得一個KEY的值

SETEX key seconds value :   設(shè)置KEY的VALUE和EXP時間

SETNX key value :           設(shè)置KEY的VALUE,前提是KEY之前不存在

SET key value :             設(shè)置KEY,VALUE

APPEND key value :          向一個KEY擴展一個值

DEBUG OBJECT key :          獲得一個KEY的DEBUG信息

DECR key :                  給一個KEY-1

DECRBY key integer :        給一個KEY-integer

EXISTS key :                判斷一個KEY是否存在

EXPIRE key seconds :        設(shè)定一個KEY的TTL(second)

EXPIREAT key timestamp :    設(shè)定一個KEY的TTL(unix timestamp)

TTL key :                   獲得KEY的TTL

PERSIST key :               刪除一個KEY的過期標(biāo)志

KEYS pattern :              查找所有符合PATTERN的KEY

MOVE key db :               將一個KEY移動到另一個DATABASE中

RENAME key newkey :         重命名一個KEY

RENAMENX key newkey :       給一個KEY重命名,前提是新KEYNAME不存在

RANDOMKEY :                 從KEYSPACE返回一個任一的KEY

<<ABOUT VALUE>>

GETRANGE key start end :            獲得KEY對應(yīng)的字符串里指定范圍的子串

GETSET key value :                  設(shè)置KEY對應(yīng)的VALUE,并返回老的VALUE

INCR key :                          為KEY對應(yīng)的整數(shù)值自增1

INCRBY key increment :              為KEY對應(yīng)的整數(shù)值自增increment

MGET key [key ...] :                獲得所有指定KEY的值

MSET key value [key value ...] :    為指定的KEYS設(shè)置指定的VALUES

MSETNX key value [key value ...] :  當(dāng)指定的KEY存在時候,為指定的KEYS設(shè)置指定的VALUES

STRLEN key :                        獲得KEY的VALUE長度

<<ABOUT SERVER>>

INFO :                                          獲得服務(wù)器的狀態(tài)信息和統(tǒng)計信息

MONITOR :                                       實時監(jiān)聽SERVER獲得的所有請求

PING :                                          Ping服務(wù)器

QUIT :                                          關(guān)閉鏈接

PUBLISH channel message :                       發(fā)布一個消息到一個CHANNEL

AUTH password :                                 認(rèn)證服務(wù)器

LASTSAVE :                                      獲得最后一次成功SAVETODISK的時間戳

OBJECT subcommand [arguments [arguments ...]] : 偵測REDIS對象的內(nèi)部

PSUBSCRIBE pattern [pattern ...] :              監(jiān)聽發(fā)布到CHANNEL的所有符合PATTERN的消息

PUNSUBSCRIBE [pattern [pattern ...]] :          停止監(jiān)聽發(fā)布到CHANNEL的所有符合PATTERN的消息

CONFIG RESETSTAT :                              重設(shè)INFO命令返回的狀態(tài)信息

SUBSCRIBE channel [channel ...] :               監(jiān)聽指定CHANNEL的消息

UNSUBSCRIBE [channel [channel ...]] :           停止監(jiān)聽指定CHANNEL的消息

UNWATCH : Forget about all watched keys         停止監(jiān)視所有被監(jiān)視的KEY

WATCH key [key ...] :                           監(jiān)視所有給定的KEY,來判斷MULTI和EXEC塊的執(zhí)行

<<ABOUT DATABASE>>

SAVE Synchronously :    保存DATASET到硬盤

SELECT index :          切換當(dāng)前數(shù)據(jù)庫

BGSAVE :                異步保存DATASET到硬盤

DBSIZE :                    返回一個DATABASE的KEY總數(shù)

FLUSHALL :                  刪除所有DATABASE上所有的KEY

FLUSHDB :                   刪除當(dāng)前DATABASE上所有的KEY

SHUTDOWN Synchronously :                        保存DATASET到硬盤后,關(guān)閉服務(wù)器

<<CONFIGURE>>

CONFIG GET parameter :          獲得一個配置參數(shù)值

CONFIG SET parameter value :    設(shè)置一個配置參數(shù)為給定值

<<OTHER>>

GETBIT key offset :             返回KEY對應(yīng)的VALUE在OFFSET的比特值

MULTI :                         標(biāo)識一個業(yè)務(wù)塊的開始

SETRANGE key offset value :     從指定的OFFSET開始覆蓋寫KEY對應(yīng)的VALUE串

BGREWRITEAOF :                  異步重寫append-only file

DEBUG SEGFAULT :                使服務(wù)器crash

DISCARD :                       忽略所有的以MULTI開頭的命令

ECHO message :                  ECHO message

EXEC :                          執(zhí)行所有以MULTI開頭的命令

SLAVEOF host port :             使本服務(wù)器成為另一REDIS HOST的SLAVE,或者使本服務(wù)器成為主服務(wù)器

SYNC :                          內(nèi)部備份命令

LINSERT key BEFORE|AFTER refvalue value : 向列表key的refvalue之前或者之后插入value

到此,相信大家對“redis數(shù)據(jù)結(jié)構(gòu)有哪些內(nèi)容”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI