Redis對象——列表(List)

系列文章

最新:Redis持久化——如何選擇合適的持久化方式html

最新:Redis持久化——AOF日誌redis

最新:Redis持久化——內存快照(RDB)數據結構

一文回顧Redis五大對象(數據類型)app

Redis對象——有序集合(ZSet)運維

Redis對象——集合(Set)性能

Redis對象——列表(List)學習

Redis對象——哈希(Hash)ui

Redis數據結構——quicklist編碼

Redis對象——字符串設計

Redis對象——Redis對象系統簡介

Redis數據結構——壓縮列表

Redis數據結構——整數集合

Redis數據結構——跳躍表

Redis數據結構——字典

Redis數據結構——鏈表

Redis數據結構——簡單動態字符串SDS

列表(list)類型是用來存儲多個有序的字符串,列表中的每一個字符串稱爲元素(element),一個列表最多能夠存儲232-1個元素。在Redis中,能夠對列表兩端插入(push)和彈出(pop),還能夠獲取指定範圍的元素列表、獲取指定索引下標的元素等。列表是一種比較靈活的數據結構,它能夠充當棧和隊列的角色,在實際開發上有不少應用場景。

列表類型有兩個特色:

  1. 列表中的元素是有序的,這就意味着能夠經過索引下標獲取某個元素或者某個範圍內的元素列表。
  2. 列表中的元素能夠是重複的.

1、內部實現

在Redis3.2版本之前列表類型的內部編碼有兩種。

  • ziplist(壓縮列表):當列表的元素個數小於list-max-ziplist-entries配置(默認512個),同時列表中每一個元素的值都小於list-max-ziplist-value配置時(默認64字節),Redis會選用ziplist來做爲列表的內部實現來減小內存的使用。
  • linkedlist(鏈表):當列表類型沒法知足ziplist的條件時,Redis會使用linkedlist做爲列表的內部實現。

而在Redis3.2版本開始對列表數據結構進行了改造,使用 quicklist 代替了 ziplist 和 linkedlist.

關於這三種底層數據結構能夠查看個人另外三篇文章

Redis數據結構——鏈表

Redis數據結構——壓縮列表

Redis數據結構——quicklist

2、經常使用命令

Redis列表對象經常使用命令以下表(點擊命令可查看命令詳細說明)。

命令 說明 時間複雜度
BLPOP key [key ...] timeout 刪除,並得到該列表中的第一元素,或阻塞,直到有一個可用 O(1)
BRPOP key [key ...] timeout 刪除,並得到該列表中的最後一個元素,或阻塞,直到有一個可用 O(1)
BRPOPLPUSH source destination timeout 彈出一個列表的值,將它推到另外一個列表,並返回它;或阻塞,直到有一個可用 O(1)
LINDEX key index 獲取一個元素,經過其索引列表 O(N)
LINSERT key BEFORE AFTER pivot value在列表中的另外一個元素以前或以後插入一個元素 O(N)
LLEN key 得到隊列(List)的長度 O(1)
LPOP key 從隊列的左邊出隊一個元素 O(1)
LPUSH key value [value ...] 從隊列的左邊入隊一個或多個元素 O(1)
LPUSHX key value 當隊列存在時,從隊到左邊入隊一個元素 O(1)
LRANGE key start stop 從列表中獲取指定返回的元素 O(S+N)
LREM key count value 從列表中刪除元素 O(N)
LSET key index value 設置隊列裏面一個元素的值 O(N)
LTRIM key start stop 修剪到指定範圍內的清單 O(N)
RPOP key 從隊列的右邊出隊一個元 O(1)
RPOPLPUSH source destination 刪除列表中的最後一個元素,將其追加到另外一個列表 O(1)
RPUSH key value [value ...] 從隊列的右邊入隊一個元素 O(1)
RPUSHX key value 從隊列的右邊入隊一個元素,僅隊列存在時有效 O(1)

3、使用場景

3.1 消息隊列

列表類型可使用 rpush 實現先進先出的功能,同時又可使用 lpop 輕鬆的彈出(查詢並刪除)第一個元素,因此列表類型能夠用來實現消息隊列

3.2 文章(商品等)列表

咱們以博客站點爲例,當用戶和文章都愈來愈多時,爲了加快程序的響應速度,咱們能夠把用戶本身的文章存入到 List 中,由於 List 是有序的結構,因此這樣又能夠完美的實現分頁功能,從而加速了程序的響應速度。

  1. 每篇文章咱們使用哈希結構存儲,例如每篇文章有3個屬性title、timestamp、content

    hmset acticle:1 title xx timestamp 1476536196 content xxxx
    ...
    hmset acticle:k title yy timestamp 1476512536 content yyyy
    ...
  2. 向用戶文章列表添加文章,user:{id}:articles做爲用戶文章列表的鍵:

    lpush user:1:acticles article:1 article3
    ...
    lpush
    ...
  3. 分頁獲取用戶文章列表,例以下面僞代碼獲取用戶id=1的前10篇文章

    articles = lrange user:1:articles 0 9
    for article in {articles}
    {
    	hgetall {article}
    }

注意:使用列表類型保存和獲取文章列表會存在兩個問題。

  • 若是每次分頁獲取的文章個數較多,須要執行屢次hgetall操做,此時能夠考慮使用Pipeline批量獲取,或者考慮將文章數據序列化爲字符串類型,使用mget批量獲取。
  • 分頁獲取文章列表時,lrange命令在列表兩端性能較好,可是若是列表較大,獲取列表中間範圍的元素性能會變差,此時能夠考慮將列表作二級拆分,或者使用Redis3.2的quicklist內部編碼實現,它結合ziplist和linkedlist的特色,獲取列表中間範圍的元素時也能夠高效完成。

關於列表的使用場景可參考如下幾個命令組合:

  • lpush+lpop=Stack(棧)
  • lpush+rpop=Queue(隊列)
  • lpush+ltrim=Capped Collection(有限集合)
  • lpush+brpop=Message Queue(消息隊列)

小結

本篇文章咱們總結了Redis 列表對象的內部實現、經常使用命令以及經常使用的一些場景,那麼你們在項目中對Redis列表對象的使用都有哪些場景呢,歡迎在評論區給我留言和分享,我會第一時間反饋!咱們共同窗習與進步!

參考

《Redis設計與實現》

《Redis開發與運維》

《Redis官方文檔》

-----END-----

關注下方公衆號,回覆「Redis」,可得Redis相關學習資料

相關文章
相關標籤/搜索