Redis數據類型簡介(十分鐘快速學習Redis)

来源:https://www.cnblogs.com/daichangya/archive/2020/05/17/12903675.html
-Advertisement-
Play Games

1. "如何在ubuntu18.04上安裝和保護redis" 2. "如何連接到Redis資料庫" 3. "如何管理Redis資料庫和Keys" 4. "如何在Redis中管理副本和客戶端" 5. "如何在Redis中管理字元串" 6. "如何在Redis中管理list" 7. "如何在Redis中 ...


  1. 如何在ubuntu18.04上安裝和保護redis
  2. 如何連接到Redis資料庫
  3. 如何管理Redis資料庫和Keys
  4. 如何在Redis中管理副本和客戶端
  5. 如何在Redis中管理字元串
  6. 如何在Redis中管理list
  7. 如何在Redis中管理Hashes
  8. 如何在Redis中管理Sets
  9. 如何在Redis中管理Sorted Sets
  10. 如何在Redis中運行事務
  11. 如何使Redis中的Key失效
  12. 如何解決Redis中的問題
  13. 如何從命令行更改Redis的配置
  14. Redis數據類型簡介

Redis數據類型簡介

Redis不是_簡單的_鍵值存儲,它實際上是一個_數據結構伺服器_,支持不同類型的值。這意味著在傳統鍵值存儲中,您將字元串鍵與字元串值相關聯,而在Redis中,該值不僅限於簡單的字元串,還可以容納更複雜的數據結構。以下是Redis支持的所有數據結構的列表,本教程將分別進行介紹:

  • 二進位安全字元串。
  • 列表:根據插入順序排序的字元串元素的集合。它們基本上是_鏈表_。
  • 集:唯一,未排序的字元串元素的集合。
  • 類似於Sets的排序集合,但每個字元串元素都與一個稱為_score_的浮點值相關聯。元素總是按它們的分數排序,因此與Sets不同,可以檢索一系列元素(例如,您可能會問:給我前10名或後10名)。
  • 哈希,是由與值關聯的欄位組成的映射。欄位和值都是字元串。這與Ruby或Python哈希非常相似。
  • 位數組(或簡稱為點陣圖):可以使用特殊命令像位數組一樣處理字元串值:您可以設置和清除單個位,計數所有設置為1的位,找到第一個設置或未設置的位,等等。
  • HyperLogLogs:這是一個概率數據結構,用於估計集合的基數。別害怕,它比看起來更簡單...請參閱本教程的HyperLogLog部分。
  • 流:提供抽象日誌數據類型的類地圖項的僅追加集合。在“ Redis流簡介”中對它們進行了深入 介紹

命令參考中掌握這些數據類型的工作方式以及使用什麼來解決給定問題並不總是那麼容易,因此,本文檔是有關Redis數據類型及其最常見模式的速成課程。

對於所有示例,我們將使用該redis-cli實用程式(一個簡單但方便的命令行實用程式)對Redis伺服器發出命令。

*Redis keys

Redis密鑰是二進位安全的,這意味著您可以使用任何二進位序列作為密鑰,從“ foo”之類的字元串到JPEG文件的內容。空字元串也是有效的鍵。

有關密鑰的其他一些規則:

  • 太長的鍵不是一個好主意。例如,1024位元組的密鑰不僅是記憶體方面的問題,也是一個壞主意,而且因為在數據集中查找密鑰可能需要進行一些代價高昂的密鑰比較。即使手頭的任務是匹配一個大值的存在,對它進行散列(例如使用SHA1)也是一個更好的主意,尤其是從記憶體和帶寬的角度來看。
  • 非常短的鍵通常不是一個好主意。如果您可以改寫“ user:1000:followers”,那麼將“ u1000flw”寫為密鑰毫無意義。與鍵對象本身和值對象使用的空間相比,後者更具可讀性,並且添加的空間較小。雖然短鍵顯然會消耗更少的記憶體,但您的工作是找到合適的平衡。
  • 嘗試堅持使用架構。例如,“ object-type:id”是一個好主意,例如“ user:1000”。點或破折號通常用於多字欄位,例如“ comment:1234:reply.to”或“ comment:1234:reply-to”中。
  • 允許的最大密鑰大小為512 MB。

*Redis Strings

Redis字元串類型是您可以與Redis鍵關聯的最簡單的值類型。它是Memcached中唯一的數據類型,因此對於新手來說,在Redis中使用它也是很自然的。

由於Redis鍵是字元串,因此當我們也使用字元串類型作為值時,我們會將一個字元串映射到另一個字元串。字元串數據類型對於許多用例很有用,例如緩存HTML片段或頁面。

讓我們使用來處理字元串類型redis-cli(所有示例將redis-cli在本教程中通過來執行)。

> set mykey somevalue
OK
> get mykey
"somevalue"

如您所見,使用SETGET命令是我們設置和檢索字元串值的方式。請註意,即使鍵已與非字元串值相關聯,SET仍將替換已存儲在鍵中的任何現有值。因此SET執行分配。

值可以是每種類型的字元串(包括二進位數據),例如,您可以在值記憶體儲jpeg圖像。值不能大於512 MB。

SET命令有有趣的選項,這是作為附加參數。例如,如果密鑰已經存在,我可能會要求SET失敗,或者相反,只有密鑰已經存在時,它才會成功:

> set mykey newval nx
(nil)
> set mykey newval xx
OK

即使字元串是Redis的基本值,您也可以使用它們執行一些有趣的操作。例如,一個是原子增量:

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

INCR命令由一個解析字元串值作為一個整數,它的增量,並最終將獲得的值作為新的值。還有其他類似的命令,例如INCRBYDECRDECRBY。在內部,它始終是相同的命令,其執行方式略有不同。

INCR是原子的意味著什麼?即使使用相同密鑰發出INCR的多個客戶也永遠不會進入競爭狀態。例如,客戶端1不會同時讀取“ 10”,客戶端2會同時讀取“ 10”,都遞增為11,並將新值設置為11。最終值將始終為12,而在所有其他客戶端未同時執行命令時執行增量設置操作。

有許多用於操作字元串的命令。例如,GETSET命令將鍵設置為新值,並返回舊值作為結果。例如,如果您的系統在 每次網站接收新訪客時使用INCR遞增Redis密鑰,則可以使用此命令。您可能希望每小時收集一次此信息,而又不會丟失任何增量。您可以GETSET鍵,為其分配新值“ 0”,然後回讀舊值。

在單個命令中設置或檢索多個鍵的值的功能對於減少延遲也很有用。因此,有MSETMGET命令:

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

使用MGET時,Redis返回一個值數組。

*Altering and querying the key space

有些命令未在特定類型上定義,但是在與鍵的空間進行交互時很有用,因此可以與任何類型的鍵一起使用。

例如,EXISTS命令返回1或0表示資料庫中是否存在給定的鍵,而DEL命令則刪除鍵和關聯的值(無論該值是什麼)。

> set mykey hello
OK
> exists mykey
(integer) 1
> del mykey
(integer) 1
> exists mykey
(integer) 0

從示例中,您還可以看到DEL本身如何返回1或0,具體取決於密鑰是否已刪除(存在)(不存在具有該名稱的此類密鑰)。

有許多與密鑰空間相關的命令,但是以上兩個命令與TYPE命令一起是必不可少的,TYPE命令返回存儲在指定密鑰處的值的類型:

> set mykey x
OK
> type mykey
string
> del mykey
(integer) 1
> type mykey
none

*Redis expires: keys with limited time to live

在繼續使用更複雜的數據結構之前,我們需要討論另一個功能,該功能不管值類型如何都可以工作,並且稱為Redis expires。基本上,您可以為密鑰設置一個超時時間,這是有限的生存時間。生存時間過去後,該密鑰將自動銷毀,就像用戶使用該密鑰調用DEL命令一樣。

有關Redis的一些快速信息將過期:

  • 可以使用秒或毫秒精度進行設置。
  • 但是,到期時間解析度始終為1毫秒。
  • 有關過期的信息被覆制並保留在磁碟上,實際上Redis伺服器保持停止狀態的時間已經過去(這意味著Redis保存了密鑰過期的日期)。

設置過期時間很簡單:

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

由於第二次呼叫延遲了5秒鐘以上,因此在兩次GET呼叫之間密鑰消失了。在上面的示例中,我們使用EXPIRE來設置過期時間(也可以使用它來為已經具有密鑰的密鑰設置不同的過期時間,例如可以使用PERSIST來刪除過期並使密鑰永久持久化)。但是,我們也可以使用其他Redis命令來創建具有過期密鑰。例如,使用SET選項:

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

上面的示例使用一個字元串值設置一個密鑰,該密鑰100的到期時間為十秒鐘。稍後調用TTL命令以檢查密鑰的剩餘生存時間。

為了設置和檢查以毫秒為單位到期,檢查PEXPIRE熱釋光的命令,以及完整列表SET選項。

*Redis Lists

為瞭解釋List數據類型,最好從理論上入手,因為_List_一詞經常被信息技術人員以不正當的方式使用。例如,“ Python列表”並不是名稱(鏈接列表)所建議的,而是數組(在Ruby中,相同的數據類型實際上稱為數組)。

從非常普遍的角度來看,列表只是一系列有序元素:10,20,1,2,3是一個列表。但是,使用Array實現的List的屬性與使用_Linked List_實現的List的屬性非常不同 。

Redis列表是通過鏈接列表實現的。這意味著即使您在列表中有數百萬個元素,在列表的開頭或結尾添加新元素的操作也會_在固定時間內_執行。使用LPUSH命令將新元素添加到具有10個元素的列表的開頭的速度與將元素添加到具有1000萬個元素的列表的開頭的速度相同。

缺點是什麼?在使用Array實現的列表中,_按索引_訪問元素_的_速度非常快(恆定時間索引訪問),而在通過鏈接列表實現的列表中訪問速度不是那麼快(其中操作需要的工作量與所訪問元素的索引成比例)。

Redis列表是通過鏈接列表實現的,因為對於資料庫系統而言,至關重要的是能夠以非常快的方式將元素添加到很長的列表中。稍後您將看到,另一個強大的優勢是Redis列表可以在恆定的時間內以恆定的長度獲取。

當快速訪問大量元素的中間位置很重要時,可以使用另一種稱為排序集的數據結構。排序的集將在本教程的後面部分介紹。

*First steps with Redis Lists

所述LPUSH命令將一個新元素到一個列表,在左側(在頭部),而RPUSH命令將一個新元素到一個列表,在右側(在尾部)。最後, LRANGE命令從列表中提取元素範圍:

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

請註意,LRANGE需要兩個索引,要返回的範圍的第一個和最後一個元素。兩個索引都可以為負,告訴Redis從末尾開始計數:因此-1是列表的最後一個元素,-2是列表的倒數第二個元素,依此類推。

如您所見,RPUSH在列表的右側附加了元素,而最後的LPUSH在列表的左側附加了元素。

這兩個命令都是_可變參數命令_,這意味著您可以在單個調用中隨意將多個元素推入列表中:

> 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"

我們添加了三個元素並彈出了三個元素,因此在此命令序列的末尾,列表為空,沒有其他要彈出的元素。如果我們嘗試彈出另一個元素,則會得到以下結果:

> rpop mylist
(nil)

Redis返回NULL值,以指示列表中沒有元素。

*Common use cases for lists

列表對於許多任務很有用,以下是兩個非常有代表性的用例:

  • 記住用戶發佈到社交網路上的最新更新。
  • 使用生產者將項目推送到列表中的消費者與生產者模式進行流程之間的通信,而消費者(通常是_worker_)消耗這些項目和已執行的動作。Redis具有特殊的列表命令,以使此用例更加可靠和高效。

例如,流行的Ruby庫resquesidekiq都在後臺使用Redis列表,以實現後臺作業。

流行的Twitter社交網路 用戶發佈的最新推文放入Redis列表中。

為了逐步描述一個常見的用例,假設您的主頁顯示了在照片共用社交網路中發佈的最新照片,並且您想加快訪問速度。

  • 每次用戶發佈新照片時,我們都會使用LPUSH將其ID添加到列表中。
  • 當用戶訪問主頁時,我們LRANGE 0 9為了獲取最新發佈的10個項目。

*Capped lists

在許多用例中,我們只想使用列表來存儲_最新項目_,無論它們是什麼:社交網路更新,日誌或其他任何內容。

Redis允許我們使用列表作為上限集合,僅使用LTRIM命令記住最新的N個項目並丟棄所有最舊的項目。

LTRIM命令類似於LRANGE,但是,而不是顯示元件的規定的範圍內將其設置在該範圍作為新的列表值。給定範圍之外的所有元素都將被刪除。

一個例子將使其更加清楚:

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

上面的LTRIM命令告訴Redis僅從索引0到2列出列表元素,其他所有內容都將被丟棄。這允許一個非常簡單但有用的模式:一起執行List推操作+ List修剪操作,以便添加新元素並丟棄超出限制的元素:

LPUSH mylist <some element>
LTRIM mylist 0 999

上面的組合添加了一個新元素,並且僅將1000個最新元素納入列表。使用LRANGE,您可以訪問最重要的項目,而無需記住非常舊的數據。

註意:雖然LRANGE從技術上講是O(N)命令,但朝列表的開頭或結尾訪問較小範圍是恆定時間操作。

*Blocking operations on lists

列表具有一項特殊功能,使其適合於實現隊列,並且通常用作進程間通信系統的構建塊:阻止操作。

想象一下,您想通過一個流程將項目推入列表,然後使用不同的流程來對這些項目進行某種工作。這是通常的生產者/使用者設置,可以通過以下簡單方式實現:

  • 為了將項目推送到列表中,生產者調用LPUSH
  • 為了從列表中提取/處理項目,消費者調用RPOP

但是,有時列表可能為空,沒有任何要處理的內容,因此RPOP僅返回NULL。在這種情況下,消費者被迫等待一段時間,然後使用RPOP重試。這稱為_輪詢_,在這種情況下不是一個好主意,因為它有幾個缺點:

  1. 強制Redis和客戶端處理無用的命令(列表為空時的所有請求將無法完成任何實際工作,它們只會返回NULL)。
  2. 由於工作人員在收到NULL之後會等待一段時間,因此會增加項目處理的延遲。為了使延遲更小,我們可以在兩次調用RPOP之間等待的時間更少,從而擴大了問題編號1,即對Redis的調用更加無用。

所以,所謂的Redis命令工具BRPOPBLPOP它們的版本RPOPLPOP能夠阻止如果列表是空的:他們將回到只有當新的元素添加到列表中的來電者,或在用戶指定的超時到達。

這是我們可以在worker中使用的BRPOP調用的示例:

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

這意味著:“等待列表中的元素tasks,但如果5秒鐘後沒有可用元素,則返回”。

請註意,您可以將0用作超時來永遠等待元素,還可以指定多個列表,而不僅僅是一個列表,以便同時等待多個列表,併在第一個列表收到一個元素時得到通知。

有關BRPOP的幾點註意事項

  1. 客戶端以有序方式提供服務:第一個阻塞等待列表的客戶端,在某個元素被其他客戶端推送時首先提供服務,依此類推。
  2. 返回值與RPOP相比有所不同:它是一個包含兩個元素的數組,因為它還包含鍵的名稱,因為BRPOPBLPOP能夠阻止等待來自多個列表的元素。
  3. 如果達到超時,則返回NULL。

關於列表和阻止操作,您應該瞭解更多信息。我們建議您閱讀以下內容:

  • 使用RPOPLPUSH可以構建更安全的隊列或輪換隊列。
  • 該命令還有一個阻塞變體,稱為BRPOPLPUSH

*Automatic creation and removal of keys

到目前為止,在我們的示例中,我們無需在推入元素之前創建空列表,也無需在內部不再包含元素時刪除空列表。Redis的責任是在列表為空時刪除鍵,或者在鍵不存在並且我們試圖向其添加元素(例如,使用LPUSH)時創建一個空列表。

這不是特定於列表的,它適用於由多個元素組成的所有Redis數據類型-流,集合,排序集合和哈希。

基本上,我們可以用三個規則來總結行為:

  1. 當我們將元素添加到聚合數據類型時,如果目標鍵不存在,則在添加元素之前會創建一個空的聚合數據類型。
  2. 當我們從聚合數據類型中刪除元素時,如果該值保持為空,則鍵將自動銷毀。流數據類型是此規則的唯一例外。
  3. 調用帶有空鍵的只讀命令(例如LLEN(返回列表的長度))或寫命令刪除元素,總會產生與鍵保持空的聚合類型相同的結果。命令希望找到。

規則1的示例:

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

但是,如果密鑰存在,我們將無法對錯誤的類型執行操作:

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

規則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

彈出所有元素後,鍵不再存在。

規則3的示例:

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

*Redis Hashes

Redis散列與欄位值對看起來完全一樣,可能是人們期望的“散列”外觀:

> 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"

儘管哈希可以方便地表示_對象_,但是實際上可以放入哈希中的欄位數沒有實際限制(可用記憶體除外),因此您可以在應用程式內部以多種不同方式使用哈希。

HMSET命令設置哈希的多個欄位,而HGET檢索單個欄位。HMGET類似於HGET但返回值的數組:

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

有些命令也可以對單個欄位執行操作,例如HINCRBY

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

您可以在文檔中找到哈希命令完整列表

值得註意的是,小哈希(即,一些具有較小值的元素)以特殊方式在記憶體中進行編碼,從而使它們具有很高的記憶體效率。

*Redis Sets

Redis集是字元串的無序集合。該 SADD命令添加新的元素,一組。還可以對集合進行許多其他操作,例如測試給定元素是否已存在,執行多個集合之間的交集,並集或求差等等。

> sadd myset 1 2 3
(integer) 3
> smembers myset
1. 3
2. 1
3. 2

在這裡,我在集合中添加了三個元素,並告訴Redis返回所有元素。如您所見,它們沒有排序-Redis可以在每次調用時隨意以任何順序返回元素,因為與用戶之間沒有關於元素順序的約定。

Redis具有用於測試成員資格的命令。例如,檢查元素是否存在:

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

“ 3”是集合的成員,而“ 30”不是集合的成員。

集合非常適合表示對象之間的關係。例如,我們可以輕鬆地使用集合來實現標簽。

對這個問題進行建模的一種簡單方法是為我們要標記的每個對象設置一個集合。該集合包含與對象關聯的標簽的ID。

一個例證是標記新聞文章。如果商品ID 1000帶有標簽1、2、5和77進行標記,則集合可以將這些標簽ID與新聞項相關聯:

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

我們可能還需要逆關係:用給定標簽標記的所有新聞的列表:

> 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

要獲取給定對象的所有標簽很簡單:

> smembers news:1000:tags
1. 5
2. 1
3. 77
4. 2

註意:在示例中,我們假設您具有另一個數據結構,例如Redis哈希,它將標簽ID映射到標簽名稱。

還有其他一些非常簡單的操作,使用正確的Redis命令仍然很容易實現。例如,我們可能需要包含標簽1、2、10和27的所有對象的列表。我們可以使用SINTER命令執行此操作,該命令執行不同集合之間的交集。我們可以用:

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

除了交集之外,您還可以執行並集,求差,提取隨機元素等等。

提取元素的命令稱為SPOP,對於建模某些問題非常方便。例如,為了實現基於Web的撲克游戲,您可能需要用一組來代表您的套牌。假設我們對(C)lubs,(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

現在我們要為每個玩家提供5張卡片。該SPOP命令刪除一個隨機元素,將其返回到客戶端,所以在這種情況下完美運行。

但是,如果我們直接在甲板上對其進行稱呼,那麼在游戲的下一場比賽中,我們將需要再次填充紙牌,這可能並不理想。因此,首先,我們可以將存儲在deck密鑰中的集合複製到game:1:deck密鑰中。

這可以使用SUNIONSTORE來完成,SUNIONSTORE通常執行多個集合之間的聯合,並將結果存儲到另一個集合中。但是,由於單個集合的並集本身,我可以使用以下命令複製我的卡組:

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

現在,我準備為第一位玩家提供五張牌:

> 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"

一副千斤頂,不是很好...

現在是引入set命令的好時機,該命令提供集合中元素的數量。 在集合理論的上下文中,這通常稱為_集合_的_基數_,因此Redis命令稱為SCARD

> scard game:1:deck
(integer) 47

數學原理:52-5 = 47。

當您只需要獲取隨機元素而不將其從集合中刪除時,可以使用適合該任務的SRANDMEMBER命令。它還具有返回重覆元素和非重覆元素的功能。

*Redis Sorted sets

排序集是一種數據類型,類似於集合和哈希之間的混合。像集合一樣,排序集合由唯一的,非重覆的字元串元素組成,因此從某種意義上說,排序集合也是一個集合。

但是,雖然集內的元素沒有排序,但排序後的集合中的每個元素都與一個稱為_得分_的浮點值相關聯 (這就是為什麼該類型也類似於哈希的原因,因為每個元素都映射到一個值)。

此外,已排序集合中的元素是按_順序進行的_(因此,它們不是應請求而排序的,順序是用於表示已排序集合的數據結構的特殊性)。它們按照以下規則排序:

  • 如果A和B是兩個分數不同的元素,則如果A.score是> B.score,則A>B。
  • 如果A和B的分數完全相同,那麼如果A字元串在字典上大於B字元串,則A>B。A和B字元串不能相等,因為排序集僅具有唯一元素。

讓我們從一個簡單的示例開始,添加一些選定的黑客名稱作為排序的集合元素,並以其出生年份為“得分”。

> 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

如您所見,ZADDSADD相似,但是使用一個額外的參數(放置在要添加的元素之前)作為得分。 ZADD也是可變參數,因此即使上面的示例中未使用它,您也可以自由指定多個得分-值對。

使用排序集,返回按其出生年份排序的黑客列表很簡單,因為實際上_他們已經被排序了_。

實施說明:排序集是通過包含跳過列表和哈希表的雙埠數據結構實現的,因此,每次添加元素時,Redis都會執行O(log(N))操作。很好,但是當我們要求排序元素時,Redis根本不需要做任何工作,它已經全部排序了:

> 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表示從元素索引0到最後一個元素(-1的工作方式與LRANGE命令的情況相同)。

如果我想按相反的順序訂購(最小到最大)怎麼辦?使用ZREVRANGE而不是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"

也可以使用以下WITHSCORES參數返回分數:

> 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"

*Operating on ranges

排序集比這更強大。它們可以在範圍內操作。讓我們獲取所有在1950年(含)之前出生的人。我們使用ZRANGEBYSCORE命令來做到這一點:

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

我們要求Redis返回分數在負無窮大和1950之間的所有元素(包括兩個極端)。

也可以刪除元素範圍。讓我們從排序集中刪除所有1940年至1960年之間出生的黑客:

> zremrangebyscore hackers 1940 1960
(integer) 4

ZREMRANGEBYSCORE可能不是最好的命令名稱,但是它可能非常有用,並返回已刪除元素的數量。

為排序的集合元素定義的另一個極其有用的操作是get-rank操作。可以問一個元素在有序元素集合中的位置是什麼。

> zrank hackers "Anita Borg"
(integer) 4

ZREVRANK命令也可以為了獲得軍銜,考慮的要素排序的下降方式。

*Lexicographical scores

在最新版本的Redis 2.8中,引入了一項新功能,該功能允許按字典順序獲取範圍,假設已排序集中的元素都以相同的相同分數插入(將元素與C memcmp函數進行比較 ,因此可以確保沒有排序規則) ,並且每個Redis實例將以相同的輸出進行回覆)。

用於按字典順序操作的主要命令是ZRANGEBYLEXZREVRANGEBYLEXZREMRANGEBYLEXZLEXCOUNT

例如,讓我們再次添加我們的著名黑客列表,但是這次對所有元素使用零分:

> 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"

由於排序集的排序規則,它們已經按字典順序排序:

> 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"

範圍可以是包含(inclusive)或排除(exclusive)(取決於第一個字元),字元串無限和負無限分別用+-字元串指定。有關更多信息,請參見文檔。

此功能非常重要,因為它允許我們將排序後的集合用作通用索引。例如,如果要通過128位無符號整數參數索引元素,則只需將元素添加到具有相同分數(例如0)但具有由128個位元組組成的16位元組首碼的排序集中大尾數中的位數。由於big endian中的數字實際上按數字順序也按字典順序(以原始位元組順序)排序,因此您可以要求128位空間中的範圍,並獲得丟棄首碼的元素值。

如果要在更嚴重的演示環境中查看該功能,請檢查Redis自動完成演示

*Updating the score: leader boards

在切換到下一個主題之前,請只對已排序集做最後的說明。排序集的分數可以隨時更新。只需對已包含在排序集中的元素調用ZADD,將以O(log(N))時間複雜度更新其得分(和位置)。這樣,當有大量更新時,排序集是合適的。

由於這種特性,常見的用例是排行榜。典型的應用是Facebook游戲,您可以將按高分對用戶進行排序的能力與獲得排名的操作結合起來,以顯示前N名的用戶以及排行榜中的用戶排名(例如,“您是這裡的#4932最佳成績”)。

*Bitmaps

點陣圖不是實際的數據類型,而是在String類型上定義的一組面向位的操作。由於字元串是二進位安全Blob,並且最大長度為512 MB,因此它們適合設置多達2 32個不同的位。

位操作分為兩類:固定時間的單個位操作(如將一個位設置為1或0或獲取其值),以及對位組的操作,例如計算給定位範圍內設置的位的數量(例如,人口計數)。

點陣圖的最大優點之一是,它們在存儲信息時通常可以節省大量空間。例如,在以增量用戶ID表示不同用戶的系統中,僅使用512 MB記憶體就可以記住40億用戶的一位信息(例如,知道用戶是否要接收新聞通訊)。

使用SETBITGETBIT命令設置和檢索位:

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

所述SETBIT命令採用作為第一個參數的比特數,和作為第二個參數的值以設置所述位,其為1或0的命令自動放大字元串,如果定址位是當前字元串長度之外。

GETBIT只是返回指定索引處的位的值。超出範圍的位(定址超出存儲在目標鍵中的字元串長度的位)始終被視為零。

在位組上有三個命令:

  1. BITOP在不同的字元串之間執行按位運算。提供的運算為AND,OR,XOR和NOT。
  2. BITCOUNT執行填充計數,報告設置為1的位數。
  3. BITPOS查找指定值為0或1的第一位。

無論BITPOS比特計數能夠與字元串的位元組範圍進行操作,而不是該字元串的整個長度運行。以下是BITCOUNT調用的一個簡單示例:

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

點陣圖的常見用例是:

  • 各種實時分析。
  • 存儲與對象ID相關的空間高效但高性能的布爾信息。

例如,假設您想知道網站用戶每天訪問量最長的時間。您從零開始計算天數,即從您公開網站的那一天開始,併在用戶每次訪問該網站時對SETBIT進行設置。作為位索引,您只需花費當前的unix時間,減去初始偏移量,然後除以一天中的秒數(通常為3600 * 24)。

這樣,對於每個用戶,您都有一個小的字元串,其中包含每天的訪問信息。使用BITCOUNT,可以輕鬆獲得給定用戶訪問網站的天數,而只需幾個BITPOS調用,或者僅獲取和分析客戶端的點陣圖,就可以輕鬆計算最長的連勝記錄。

點陣圖很容易分成多個鍵,例如,為了分片數據集,並且因為通常最好避免使用大鍵。要在不同的密鑰上拆分點陣圖,而不是將所有位都設置為密鑰,一個簡單的策略就是為每個密鑰存儲M位,並使用來獲取密鑰名稱,使用來獲取bit-number/M第N位bit-number MOD M

*HyperLogLogs

HyperLogLog是一種概率數據結構,用於對唯一事物進行計數(從技術上講,這是指估計集合的基數)。通常,對唯一項目進行計數需要使用與要計數的項目數量成比例的記憶體量,因為您需要記住過去已經看到的元素,以避免多次對其進行計數。但是,有一組演算法會以記憶體為代價來交換精度:您最終會得到帶有標準誤差的估計量度,在Redis實現的情況下,該誤差小於1%。這種演算法的神奇之處在於,您不再需要使用與所計數項目數量成正比的記憶體量,而是可以使用恆定數量的記憶體!在最壞的情況下為12k位元組,如果您的HyperLogLog(從現在開始將它們稱為HLL)看到的元素很少,則少得多。

Redis中的HLL儘管在技術上是不同的數據結構,但被編碼為Redis字元串,因此您可以調用GET來序列化HLL,然後調用SET 來將其反序列化回伺服器。

從概念上講,HLL API就像使用Set來執行相同的任務。你會 薩德每個觀測元素為一組,並且將使用SCARD檢查組中的元素,這是唯一的數量自SADD不會再添加一個現有的元素。

儘管您並未真正_將項目添加_到HLL中,但由於數據結構僅包含不包含實際元素的狀態,因此API相同:

  • 每次看到新元素時,都可以使用PFADD將其添加到計數中。

  • 到目前為止,每次您要檢索_添加_到PFADD的唯一元素的當前近似值時,都可以使用PFCOUNT

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

該數據結構用例的一個例子是每天計算用戶在搜索表單中執行的唯一查詢。

Redis也能夠執行HLL的合併,請查看 完整的文檔以獲取更多信息。

*Other notable features

Redis API中還有其他重要內容,在本文檔的上下文中無法探討,但值得您註意:

*Learn more

本教程絕不完整,僅涵蓋了API的基礎知識。閱讀命令參考以發現更多內容。

感謝您的閱讀,並祝您使用Redis玩得開心!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • [在Docker中使用Redis] [Redis Cli] [命令的返回值類型] [Redis中的多資料庫] [基礎命令] Redis是REmote DIctionary Server(遠程字典伺服器)的縮寫,它以字典結構存儲數據,並允許其他應用通過TCP協議讀寫字典中的內容。 Redis資料庫中的 ...
  • 除了RDB持久化功能之外,Redis還提供了AOF持久化功能。與RDB持久化通過保存資料庫中的鍵值對來記錄資料庫狀態不同,AOF持久化是通過保存Redis伺服器所執行的寫命令來記錄資料庫狀態的。 伺服器在啟動時,可以通過載入和執行AOF文件中保存的命令來還原伺服器關閉前的資料庫狀態。 AOF持久化功 ...
  • MySQL 5.7.26 二進位版本安裝(免安裝綠色版) 下載地址 https://downloads.mysql.com/archives/community/ https://cdn.mysql.com/archives/mysql-5.7/mysql-5.7.26-linux-glibc2.1 ...
  • 今天使用新創建的用戶登錄mysql時被提示 Access denied for user '-Mike'@'localhost' (using password: YES) 操作步驟: 成功!!!(雖然不知道為啥) 有無野生大佬給解答一下 ...
  • Redis是記憶體資料庫,它將自己的資料庫狀態存儲在記憶體裡面,所以如果不想辦法將存儲在記憶體中的資料庫狀態保存到磁碟,那麼伺服器 進程一旦退出,伺服器中的資料庫狀態也會消失不見。 為瞭解決這個問題,Redis提供了RDB持久化功能,這個功能可以將資料庫狀態保存到磁碟裡面 1、RDB文件的創建與載入 Re ...
  • 1、下載Navicat Premium Navicat15鏈接:http://www.navicat.com.cn/download/navicat-premium,選擇相應版本,這裡選擇window 64位。 2、安裝客戶端沒啥好說的,直接省略。 3、下載激活軟體, 無需斷網運行激活軟體Navic ...
  • 近段時間發現公司的HDP大數據平臺的tez-ui頁面不能用了,頁面顯示為空,導致通過hive提交的sql不能方便地查找到Yarn上對應的applicationId,只能通過beeline的屏幕輸出信息、hiveserver2的日誌、yarn的日誌等一步步去查找,非常麻煩(查找方法見上一篇博客“如何找 ...
  • 1. "如何在ubuntu18.04上安裝和保護redis" 2. "如何連接到Redis資料庫" 3. "如何管理Redis資料庫和Keys" 4. "如何在Redis中管理副本和客戶端" 5. "如何在Redis中管理字元串" 6. "如何在Redis中管理list" 7. "如何在Redis中 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...