溫馨提示×

溫馨提示×

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

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

NoSQL----Redis 2.4--List

發(fā)布時間:2020-05-29 13:11:11 來源:網(wǎng)絡 閱讀:277 作者:lzf05303774 欄目:關(guān)系型數(shù)據(jù)庫

一、概述:

1、List:允許出現(xiàn)重復的元素,list可以作為棧(先進后出)或者隊列(先進先出)。

頭元素和尾元素:頭元素指的是列表左端/前端第一個元素;尾元素指的是列表右端/后端第一個元素。

舉個例子,列表list包含三個元素:x, y, z,其中x是頭元素,而z則是尾元素。

空列表:指不包含任何元素的列表,Redis將不存在的key也視為空列表。

2、鏈表結(jié)構(gòu)的小技巧:

      針對鏈表結(jié)構(gòu)的Value,Redis在其官方文檔中給出了一些實用技巧,如RPOPLPUSH命令,下面給出具體的解釋。

      Redis鏈表經(jīng)常會被用于消息隊列的服務,以完成多程序之間的消息交換。假設一個應用程序正在執(zhí)行LPUSH操作向鏈表中添加新的元素,我們通常將這樣的程序稱之為"生產(chǎn)者(Producer)",而另外一個應用程序正在執(zhí)行RPOP操作從鏈表中取出元素,我們稱這樣的程序為"消費者(Consumer)"。如果此時,消費者程序在取出消息元素后立刻崩潰,由于該消息已經(jīng)被取出且沒有被正常處理,那么我們就可以認為該消息已經(jīng)丟失,由此可能會導致業(yè)務數(shù)據(jù)丟失,或業(yè)務狀態(tài)的不一致等現(xiàn)象的發(fā)生。然而通過使用RPOPLPUSH命令,消費者程序在從主消息隊列中取出消息之后再將其插入到備份隊列中,直到消費者程序完成正常的處理邏輯后再將該消息從備份隊列中刪除。同時我們還可以提供一個守護進程,當發(fā)現(xiàn)備份隊列中的消息過期時,可以重新將其再放回到主消息隊列中,以便其它的消費者程序繼續(xù)處理。

二、應用場景:

        獲得最新的10個登錄用戶信息:

1、使用數(shù)據(jù)庫方式需執(zhí)行如下sql語句:

select * from loginuser order by logintime desc limit 10;

但是數(shù)據(jù)多的時候,全部數(shù)據(jù)都要受到影響,對數(shù)據(jù)庫的負載比較高,

必要情況還要需要對關(guān)鍵字段logintime設置索引,索引也比較耗費系統(tǒng)資源。


2、如果通過redis的list鏈表實現(xiàn)以上功能,就非常簡單??梢栽趌ist鏈表中只保留最新的10個登錄用戶,每進來一個新數(shù)據(jù)就刪除一個舊數(shù)據(jù),每次就可以從鏈表中直接獲得需要的資源,極大節(jié)省各方面的資源。

3、redis的list還能緩存一些不經(jīng)常修改的系統(tǒng)配置信息。

如緩存地址信息(國家、省份、城市、街道)、緩存用戶信息等等。


三、常用操作:

1、lpush(left push)方法:


LPUSH key value [value ...]

將一個或多個值value插入到列表key的表頭。

如果有多個value值,那么各個value值按從左到右的順序依次插入到表頭:比如對一個空列表(mylist)執(zhí)行LPUSH mylist a b c,則結(jié)果列表為c b a,

等同于執(zhí)行命令

LPUSH mylist a

LPUSH mylist b

LPUSH mylist c

如果key不存在,一個空列表會被創(chuàng)建并執(zhí)行LPUSH操作。

當key存在但不是列表類型時,返回一個錯誤。


例如:
# 加入單個元素

redis> LPUSH languages python
(integer) 1

# 加入重復元素

redis> LPUSH languages python
(integer) 2

redis> LRANGE languages 0 -1 # 列表允許重復元素
1) "python"
2) "python"

# 加入多個元素

redis> LPUSH mylist a b c
(integer) 3

redis> LRANGE mylist 0 -1
1) "c"
2) "b"
3) "a"

2、lpushx(left pushx)方法:

LPUSHX key value

將值value插入到列表key的表頭,當且僅當key存在并且是一個列表。

和LPUSH命令相反,當key不存在時,LPUSHX命令什么也不做。

例如:
# 情況1:對空列表執(zhí)行LPUSHX

redis> LLEN greet    # greet是一個空列表
(integer) 0

redis> LPUSHX greet "hello"  # 嘗試LPUSHX,失敗,因為列表為空
(integer) 0


# 情況2:對非空列表執(zhí)行LPUSHX

redis> LPUSH greet "hello"   # 先用LPUSH創(chuàng)建一個有一個元素的列表
(integer) 1

redis> LPUSHX greet "good morning"   # 這次LPUSHX執(zhí)行成功
(integer) 2

redis> LRANGE greet 0 -1
1) "good morning"
2) "hello"

3、rpush(right push)方法:

RPUSH key value [value ...]

將一個或多個值value插入到列表key的表尾。

如果有多個value值,那么各個value值按從左到右的順序依次插入到表尾:

比如對一個空列表(mylist)執(zhí)行RPUSH mylist a b c,則結(jié)果列表為a b c,

等同于執(zhí)行命令

RPUSH mylist a、

RPUSH mylist b、

RPUSH mylist c。

如果key不存在,一個空列表會被創(chuàng)建并執(zhí)行RPUSH操作。

當key存在但不是列表類型時,返回一個錯誤。


備注:在Redis 2.4版本以前的RPUSH命令,都只接受單個value值。

# 添加單個元素

redis> RPUSH languages c
(integer) 1

# 添加重復元素

redis> RPUSH languages c
(integer) 2

redis> LRANGE languages 0 -1 # 列表允許重復元素
1) "c"
2) "c"

# 添加多個元素

redis> RPUSH mylist a b c
(integer) 3

redis> LRANGE mylist 0 -1
1) "a"
2) "b"
3) "c"

4、rpushx(right pushx)方法:

RPUSHX key value

將值value插入到列表key的表尾,當且僅當key存在并且是一個列表。

和RPUSH命令相反,當key不存在時,RPUSHX命令什么也不做。


例如:
# 情況1:key不存在

redis> LLEN greet
(integer) 0

redis> RPUSHX greet "hello"  # 對不存在的key進行RPUSHX,PUSH失敗。
(integer) 0


# 情況2:key存在且是一個非空列表

redis> RPUSH greet "hi"  # 先用RPUSH插入一個元素
(integer) 1

redis> RPUSHX greet "hello"  # greet現(xiàn)在是一個列表類型,RPUSHX操作成功。
(integer) 2

redis> LRANGE greet 0 -1
1) "hi"
2) "hello"

5、lpop(left pop)方法:

LPOP key

移除并返回列表key的頭元素。

redis> LLEN course
(integer) 0

redis> RPUSH course algorithm001
(integer) 1
redis> RPUSH course c++101
(integer) 2

redis> LPOP course  # 移除頭元素
"algorithm001"

6、rpop(right pop)方法:

RPOP key

移除并返回列表key的尾元素。

redis> RPUSH mylist "one"
(integer) 1
redis> RPUSH mylist "two"
(integer) 2
redis> RPUSH mylist "three"
(integer) 3

redis> RPOP mylist  # 返回被彈出的元素
"three"

redis> LRANGE mylist 0 -1   # 列表剩下的元素
1) "one"
2) "two"

7、llen方法:

LLEN key

返回列表key的長度。

如果key不存在,則key被解釋為一個空列表,返回0.

如果key不是列表類型,返回一個錯誤。

# 情況1:空列表

redis> LLEN job
(integer) 0

# 情況2:非空列表
redis> LPUSH job "cook food"
(integer) 1
redis> LPUSH job "have lunch"
(integer) 2

redis> LLEN job
(integer) 2

8、lrange方法:

LRANGE key start end

返回列表key中指定區(qū)間內(nèi)的元素,區(qū)間以偏移量start和end指定。

下標(index)參數(shù)start和end都以0為底,也就是說,以0表示列表的第一個元素,以1表示列表的第二個元素,以此類推。

你也可以使用負數(shù)下標,以-1表示列表的最后一個元素,-2表示列表的倒數(shù)第二個元素,以此類推。

超出范圍的下標

超出范圍的下標值不會引起錯誤。

如果start下標比列表的最大下標end(LLEN list減去1)還要大,或者start > stop,LRANGE返回一個空列表。

如果stop下標比end下標還要大,Redis將stop的值設置為end。


redis> RPUSH fp-language lisp   # 插入一個值到列表fp-language
(integer) 1
redis> LRANGE fp-language 0 0
1) "lisp"

redis> RPUSH fp-language scheme
(integer) 2
redis> LRANGE fp-language 0 1
1) "lisp"
2) "scheme"

9、linsert方法:


LINSERT key BEFORE|AFTER pivot value

將值value插入到列表key當中,位于值pivot之前或之后。

當pivot不存在于列表key時,不執(zhí)行任何操作。

當key不存在時,key被視為空列表,不執(zhí)行任何操作。

如果key不是列表類型,返回一個錯誤。

redis> RPUSH mylist "Hello"
(integer) 1
redis> RPUSH mylist "World"
(integer) 2

redis> LINSERT mylist BEFORE "World" "There"
(integer) 3

redis> LRANGE mylist 0 -1
1) "Hello"
2) "There"
3) "World"

redis> LINSERT mylist BEFORE "go" "let's"    # 對一個非空列表插入,查找一個不存在的pivot
(integer) -1    # 失敗

redis> EXISTS fake_list  # 對一個空列表執(zhí)行LINSERT命令
(integer) 0

redis> LINSERT fake_list BEFORE "nono" "gogogog"
(integer) 0 # 失敗

10、lset方法:

LSET key index value

將列表key下標為index的元素的值替換為value。

更多信息請參考LINDEX操作。

當index參數(shù)超出范圍,或?qū)σ粋€空列表(key不存在)進行LSET時,返回一個錯誤。


# 情況1:對空列表(key不存在)進行LSET

redis> EXISTS list
(integer) 0

redis> LSET list 0 item
(error) ERR no such key


# 情況2:對非空列表進行LSET

redis> LPUSH job "cook food"
(integer) 1

redis> LRANGE job 0 0
1) "cook food"

redis> LSET job 0 "play game"
OK

redis> LRANGE job  0 0
1) "play game"


# 情況3:index超出范圍

redis> LLEN list # 列表長度為1
(integer) 1

redis> LSET list 3 'out of range'
(error) ERR index out of range

11、lrem方法:

LREM key count value

根據(jù)參數(shù)count的值,移除列表中與參數(shù)value相等的元素。

count的值可以是以下幾種:

count > 0: 從表頭開始向表尾搜索,移除與value相等的元素,數(shù)量為count。

count < 0: 從表尾開始向表頭搜索,移除與value相等的元素,數(shù)量為count的絕對值。

count = 0: 移除表中所有與value相等的值。

# 先創(chuàng)建一個表,內(nèi)容排列是
# morning hello morning helllo morning

redis> LPUSH greet "morning"
(integer) 1
redis> LPUSH greet "hello"
(integer) 2
redis> LPUSH greet "morning"
(integer) 3
redis> LPUSH greet "hello"
(integer) 4
redis> LPUSH greet "morning"
(integer) 5

redis> LRANGE greet 0 4 # 查看所有元素
1) "morning"
2) "hello"
3) "morning"
4) "hello"
5) "morning"

redis> LREM greet 2 morning  # 移除從表頭到表尾,最先發(fā)現(xiàn)的兩個morning
(integer) 2  # 兩個元素被移除

redis> LLEN greet   # 還剩3個元素
(integer) 3

redis> LRANGE greet 0 2
1) "hello"
2) "hello"
3) "morning"

redis> LREM greet -1 morning  # 移除從表尾到表頭,第一個morning
(integer) 1

redis> LLEN greet
(integer) 2

redis> LRANGE greet 0 1
1) "hello"
2) "hello"

redis> LREM greet 0 hello  # 移除表中所有hello
(integer) 2  # 兩個hello被移除

redis> LLEN greet
(integer) 0

12、ltrim方法:

LTRIM key start stop

對一個列表進行修剪(trim),就是說,讓列表只保留指定區(qū)間內(nèi)的元素,不在指定區(qū)間之內(nèi)的元素都將被刪除。

舉個例子,執(zhí)行命令LTRIM list 0 2,表示只保留列表list的前三個元素,其余元素全部刪除。

下標(index)參數(shù)start和stop都以0為底,也就是說,以0表示列表的第一個元素,以1表示列表的第二個元素,以此類推。

你也可以使用負數(shù)下標,以-1表示列表的最后一個元素,-2表示列表的倒數(shù)第二個元素,以此類推。

當key不是列表類型時,返回一個錯誤。


# 情況1:一般情況下標

redis> LRANGE alpha 0 -1 # 建立一個5元素的列表
1) "h"
2) "e"
3) "l"
4) "l"
5) "o"

redis> LTRIM alpha 1 -1  # 刪除索引為0的元素
OK

redis> LRANGE alpha 0 -1 # "h"被刪除
1) "e"
2) "l"
3) "l"
4) "o"


# 情況2:stop下標比元素的最大下標要大

redis> LTRIM alpha 1 10086
OK
redis> LRANGE alpha 0 -1
1) "l"
2) "l"
3) "o"


# 情況3:start和stop下標都比最大下標要大,且start < sotp

redis> LTRIM alpha 10086 200000
OK
redis> LRANGE alpha 0 -1 # 整個列表被清空,等同于DEL alpha
(empty list or set)


# 情況4:start > stop

redis> LRANGE alpha 0 -1 # 在新建一個列表
1) "h"
2) "u"
3) "a"
4) "n"
5) "g"
6) "z"

redis> LTRIM alpha 10086 4
OK

redis> LRANGE alpha 0 -1 # 列表同樣被清空
(empty list or set)

13、rpoplpush方法:


RPOPLPUSH source destination

命令RPOPLPUSH在一個原子時間內(nèi),執(zhí)行以下兩個動作:

將列表source中的最后一個元素(尾元素)彈出,并返回給客戶端。

將source彈出的元素插入到列表destination,作為destination列表的的頭元素。

舉個例子,你有兩個列表source和destination,source列表有元素a, b, c,destination列表有元素x, y, z,執(zhí)行RPOPLPUSH source destination之后,source列表包含元素a, b,destination列表包含元素c, x, y, z ,并且元素c被返回。

如果source不存在,值nil被返回,并且不執(zhí)行其他動作。

如果source和destination相同,則列表中的表尾元素被移動到表頭,并返回該元素,可以把這種特殊情況視作列表的旋轉(zhuǎn)(rotation)操作。


# 相關(guān)數(shù)據(jù)

redis> RPUSH alpha a
(integer) 1
redis> RPUSH alpha b
(integer) 2
redis> RPUSH alpha c
(integer) 3
redis> RPUSH alpha d
(integer) 4

# 情況1:source和destination不同

redis> LRANGE alpha 0 -1 # 查看所有元素
1) "a"
2) "b"
3) "c"
4) "d"

redis> RPOPLPUSH alpha reciver   # 執(zhí)行一次RPOPLPUSH看看
"d"

redis> LRANGE alpha 0 -1
1) "a"
2) "b"
3) "c"

redis> LRANGE reciver 0 -1
1) "d"

redis> RPOPLPUSH alpha reciver   # 再執(zhí)行一次,確保rpop和lpush的位置正確
"c"

redis> LRANGE alpha 0 -1
1) "a"
2) "b"

redis> LRANGE reciver 0 -1
1) "c"
2) "d"


# 情況2:source和destination相同

redis> RPOPLPUSH alpha alpha
"c"

redis> LRANGE alpha 0 -1 # 原來的尾元素"c"被放到了頭部
1) "c"
2) "a"
3) "b"

14、lindex方法:

LINDEX key index

返回列表key中,下標為index的元素。

下標(index)參數(shù)start和stop都以0為底,也就是說,以0表示列表的第一個元素,以1表示列表的第二個元素,以此類推。

你也可以使用負數(shù)下標,以-1表示列表的最后一個元素,-2表示列表的倒數(shù)第二個元素,以此類推。

如果key不是列表類型,返回一個錯誤。

redis> LPUSH mylist "World"
(integer) 1

redis> LPUSH mylist "Hello"
(integer) 2

redis> LINDEX mylist 0
"Hello"

redis> LINDEX mylist -1
"World"

redis> LINDEX mylist 3  # index不在mylist的區(qū)間范圍內(nèi)
(nil)


向AI問一下細節(jié)

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

AI