運行32位仍是64位位版本的redis將決定redis鍵大小的實際限制。對於32位版原本說,任何長於32位的鍵名須要更多的字節空間,所以增長了redis的內存使用。使用64位版本的redis容許更長的鍵長度,可是對於短小的鍵來講,也會分配完整的64位空間,從而致使額外的空間浪費。前端
雖然redis官方教程data types推薦在命名鍵時使用一致的模式,可是redis自己並無模式檢測或者驗證的功能。不過能夠經過使用EXISTS和TYPE這些redis命令實現一些基本的驗證。若是應用須要明確特定類型的redis鍵是否存在於實例中,能夠經過使用EXISTS命令,隨後使用TYPE命令確認該鍵是不是指望的redis數據結構。除了這倆命令之外,驗證redis鍵語法和結構須要客戶端代碼來實現。node
若是redis應用會在不一樣的系統和組織中共享,那麼爲應用程序添加額外的驗證邏輯層將十分有用。一份精確詳盡的redis鍵模式能極大地在排查故障和調試問題方面帶來幫助。另外一種驗證redis鍵模式的方法是爲redis應用引入具體的單元測試。用來測試邊界條件、模式鍵語法和結構,還有每一個驗證過的鍵所指望的數據結構。第三種驗證redis鍵模式的方式是使用DTD或者其餘基於XML的鍵結構驗證,或者使用新的鍵驗證技術,例如 JSOB Schema.web
一份精心設計的鍵模式應當爲現存的(基於redis的)應用程序在添加新的鍵時提供指引。若是模式描述得足夠清楚而且可以保持一致性的話,那麼新的redis鍵的命名就不該當有任何神祕色彩。能夠利用名詞的單複數形式鑑別存儲到redis的實體內容與個數。redis
例如,book:1做爲redis哈希類型存儲了單一書本的相關字段,而redis鍵books:sci-fiction則存儲了一套科幻類小說。有序集合能夠用做圖書銷售排行,將books:scale-rank做爲鍵名稱,圖書銷售做爲權重(有序集合的分值),並將圖書鍵做爲值。算法
對於一個簡單的圖書應用來講,基於文本的redis模式實例以下:sql
即使是簡單的、一次性的redis項目,將鍵模式文檔添加到項目的源代碼倉庫也是一種很好的實踐。數據庫
在上例中,咱們使用「:」做爲鍵的分隔符。對於符合redis鍵來講,推薦使用冒號做爲分隔符。編程
另外一種redis鍵分隔符是英文字符句號「.」。大多數流行的編程語言,都青睞這種面向對象的語法。json
高效的redis鍵模式體如今創建命名約定以便將相關的鍵關聯起來。應用程序和業務邏輯經過客戶端代碼應用在這些鬆散耦合的redis鍵上。以以前的圖書鍵模式爲例,擴展一下需求,讓redis數據庫包含其餘媒體類型,在redis命令行工具中運行keys命令,並作一些格式化工做。咱們能夠從redis鍵模式中觀察到一種模式和隱含的關係:緩存
在此redis應用程序中,圖書和影片都提供了基本的前綴。那些用於支持的數據結構,經過基本前綴關聯到單本圖書或者單部影片,或者關聯到包含額外實體哈希的集合上。
每件做品都是有redis鍵做爲前綴,同時加上一個全局計數的哈希。在此示例中,其餘用於支持的數據結構,即圖書和影片的系列與格式,都是redis集合,其中存儲了全部圖書或者影片的鍵,並以特別的系列或者格式進行分類。舉例來講,Isaac Asimov 的 Foundation 屬性將存儲在 book:2 哈希表中。同時,book:2 又是 books:genre:sci-fiction 和 books:format:paperback 集合的成員,也是 books:sales-rank 和 all:sales-rank 有序集合中的一項。一樣地,Orson Well的 Citizen Kane 存儲在 film:1 哈希表中,同時也是 films:genre:drama 和 films:format:dvd 集合的成員,而且也是films:sale-rank 和all:sales-rank有序集合中的一項。
一般應用程序須要依據共同的特徵獲取集合的值。在圖書示例中,咱們嘗試使用KEYS命令和 books:genre:* 模式獲取全部的圖書體裁。強烈建議 不要在生產環境的應用中使用redis的keys命令,這是由於redis須要遍歷數據庫中的每一個鍵。採用一致的命名約定及諸如集合、哈希或者有序集合這樣的數據結構,應用程序理應無須使用keys命令獲取數據。雖然scan命令能夠用來獲取redis數據,但不該被視爲keys命令的替代品。scan命令抽取一個隨機的鍵片斷,而後將提供的模式和match選項應用到此隨機片斷上。回顧以前的示例,下述redis-cli 程序中運行的scan命令的用法僅對小型數據庫有效:
若是數據庫再大一點,那麼scan命令可能會沒法匹配任何數據或者只返回全部匹配數據的一個子集。所以,將全部的鍵存儲在books:genre集合中才是明智之舉,這樣應用程序就能夠像使用索引同樣,使用smembers命令快速獲取全部圖書體裁的鍵:
測試鍵之間的關係及它們是如何經過redis鍵命名約定來相互關聯的,這取決於衆多因素,其中包括應用程序是否直接與redis示例交互。添加單元測試來明確地檢測redis應用的鍵分割符及命名約定,能夠確保redis數據庫中存儲的數據精確地表達了應用程序所依賴的假設和需求。
-----------------------------------------------------------------------------------------------------------------
第一步是創建全局信紙計數器,並附加在用於出售的信紙類型和品牌的信紙前綴以後。將顏色和尺寸屬性存儲爲stationery:{id-counter}哈希中的字段,並將信紙張數存儲到另外一個stationery:{id-counter}:sheets 鍵所對應的字符串上。
10.143.128.165:6379> incr global:stationery 1
返回的整數1將用做第一個信紙的id:
10.143.128.165:6379> hmset stationery:1 color blue width '30 cm' height '40 cm' OK
爲了將紙張和stationery:1:sheets 集合關聯起來,使用increby命令:
10.143.128.165:6379> incrby stationery:1:sheets 20 20
如今,咱們再次調用incr命令爲第二種信紙類型生成id,填充哈希增長15張信紙:
10.143.128.165:6379> incr global:stationery 2 10.143.128.165:6379> hmset stationery:2 color red width '45 cm' height '45 cm' OK 10.143.128.165:6379> incrby stationery:2:sheets 15 15
接下來,特定類型的信紙包裹庫存存儲在stationery:<stationery id>:inventory 鍵模式中,鍵對應的值是簡單的整數,用來表示那種類型的信紙的可用包裹總數。
初始庫存 250件包裹:
10.143.128.165:6379> set stationery:1:inventory 250 OK
當包裹銷售出去後,stationery:1:inventory 鍵對應的整數將減去銷售的包裹數量;經銷商送來新的信紙包裹時,鍵被加上新的信紙包裹總數。
10.143.128.165:6379> decr stationery:1:inventory 249 10.143.128.165:6379> incrby stationery:1:inventory 10 259
每件包裹的銷售數據存儲在一個有序集合中。集合中每行以unix時間戳做爲分值,並以銷售數量做爲值。將stationery:1:sales做爲有序集合的redis鍵,記錄一筆20美圓的銷售:
10.143.128.165:6379> zadd stationery:1:sales 1430861194 20.00 1
對node.js來講,redis對象映射器成爲Nohm,經過使用JavaScript對象模型建立redis模式。使用Nohm爲信紙實體建模,首先須要定義信紙的JavaScript模型的顏色、高度、寬度屬性:
會產生下列redis命令:
Nohm在基礎命名模式中使用冒號做爲鍵分隔符。
1.paper:meta:version:Stationary 該redis元數據鍵存儲信紙的字符串版本。該鍵的值被設置爲一個隨機元數據版本字符串1bf8ca.....8d65c
2.paper:idsets:Stationary 該redis集合存儲了全部信紙id。該集合首先被一個負的Unix時間戳檢測,而後產生了一個值爲i9hiar...9rgc5的id字符串,並被添加到該集合中。該集合是用來追蹤信紙對象的,隨機值能夠最小化重複鍵的問題。
3.paper:meta:idGenerator:Stationary Nohm使用該redis字符串決定生成id的方法。默認的選項產生隨機字符串。遞增選項則使用整數計數器。
4.paper:meta:properties:Stationary 該redis字符串存儲了信紙對象的序列化json元數據。
5.paper:hash:Stationary:i9hira0.....9rgc5 信紙JavaScript對象把i9hira0.....9rgc5 做爲redis鍵的末尾部分,將其屬性值存儲在redis哈希中。這些操做封裝在一個事務中。
再添加第二個信紙包裹,即紅色方形,45 cm高 * 45 cm 寬,初始紙張數爲15.於是在數據庫中會有如下redis鍵:
使用Nohm爲信紙項目的銷售建模時,要使用來自 schema.org 元數據詞彙表的兩個支持類,一個名爲offer類,另外一個名爲order類。schema.org 用來表示web上的結構化數據。offer類包含了價格和可用庫用,以及用於支持其餘貨幣的priceCurency屬性,默認貨幣單位美圓。order類包含了acceptedOffer和orderDate屬性,acceptedOffer屬性鏈接到咱們爲信紙建立具體訂單。
order類包含兩個屬性,分別命名爲orderDate和orderedItem。
當交易發生時,Nohm會在offer、order、stationery這三者之間建立關聯。在使用交易發生時間建立新的訂單實例以後,Nohm使用幾個redis集合爲這三個不一樣的類之間的關係進行建模。
首先、紅色信紙的哈希鍵爲paper:hash:Offer:ia4ev....968h,並將庫存級別屬性設置爲50,價格爲15.
下一步是建立paper:relationKeys:Offer:ia4ev8....6p968h 和 paper:relations:Offer:itemOffered:Stationery:ia4ev8...968h 集合。第一個集合中存儲的鍵對應的集合中,存儲了那些經過itemOffered屬性建立offer和stationery之間的關聯。第二個集合經過建立具體的offer和stationery之間的具體關聯,存儲了全部單獨的信紙ID。
當接受訂單而且交易被確認時,redis paper:hash:Order:1 哈希使用訂單日期屬性被建立出來,同時 經過Nohm,元數據版本id使用哈希值做爲屬性被存儲。
兩個額外的集合,分別命名爲paper:relationKeys:Order:1和paper:relations:Order:offer:Offer:1,建立了order和offer之間的關聯。第一個集合爲order存儲了全部的關聯鏈接。第二個集合爲以前命令添加的order存儲了特定的offer。
redis可以爲鍵設置過時時間。經過自動化刪除過時鍵,redis應用程序可以很好的管理數據庫所使用的內存大小和使用狀況,同時減小用於追蹤數據庫中每一個鍵的客戶端代碼量。能夠對redis配置文件的選項進行設置,也能夠在運行時向redis數據庫發送命令進行設置。
redis鍵的大小應該受到限制,不只由於鍵的大小超過1024字節會致使內存增加,大尺寸的鍵還會令redis實例的開發者和用戶感到困惑。隨着redis實例大小的增加,這些過長的鍵名稱開始消耗更多的內存,從而擠壓了正常數據所需的內存空間。
一樣的,若是鍵名稱過短,額外節省的內存可能得不償失。由於對redis進行故障排除或者經過新的redis鍵添加新的功能時,會遇到各類問題。
redis的keys命令應當在萬不得已時使用,由於它對redis實例形成長時間的阻塞,甚至會致使redis內存耗盡。
scan命令爲redis中全部的鍵提供了一個迭代器,能夠對全部的鍵進行增量式調用。若是一個元素在從頭至尾的迭代中不是始終存在的,那麼scan命令並不保證該元素可以返回。
數學上對大O符號的定義爲「象徵性的表達給定函數的漸進行爲」。在計算機科學和對redis中大O符號的理解的幫助下,可以經過這些命令在面對不斷增加的輸入時的性能表現,對redis命令作出性能上的區分。
1. O(1) 隨着輸入的增長而不會對時間或者處理形成變化。性能的上線是線性時間,隨着輸入增長不會致使性能的降低,但受算法自己複雜性的限制。
2. O(log n) 對數時間,它對每一個輸入進行操做,返回的結果大於O(1),可是性能等價於對n求對數。
3.O(n) 遵循嘗試觀念,即添加額外的單元以恆定比例的量增長處理時間。
4. O(n log n) 對數線性時間, O(log n) 做用於每個輸入之上。實際上,在O(n log n)算法中每次輸入都增長了一倍以上。
5. O(n^2) 即平方時間來講,隨着n的增加,時間的量也成倍增加。對於每一個加倍的n來講,時間處理變爲原來的4倍。O(n^2) 算法的性能在n較小的狀況下也許是能夠接受的,可是當n增加到必定量時,就很快變得不切實際。
6.O(2^n) 指數時間,對於每個額外的輸入,時間都會加倍。
7. O(n!) 階乘時間,輸入的n輕微的增長都會致使處理時間太高。
根據redis文檔中爲每一個命令提供的大O符號,能夠爲任何提議的基於redis的解決方案計算出一個粗略的效率估計。一個簡單的方案就是對於必定級別的n將全部redis命令的大O符號相加,而後爲實現代碼估計大O符號,以便爲整個解決方案作粗略的時間效率估計。舉例來講,用redis實現的緩存只是簡單的set和get調用,該解決方案的大O符號就是O(1)+O(1)=2個時間單位。
對數據結構的時間複雜度的評估不只包括數據結構自己,還包括對數據進行採集與提取等redis命令總數的優化。
redis值中最基本的數據結構爲字符串,也就是和redis鍵相同的數據類型。
redis有着和其餘諸如memecached之類鍵值數據存儲解決方案類似的性能特色。
在redis中,字符串並不只僅是那些高級編程語言中包括字母數字字符的字符串,而是包含C語言(redis主要採用的編程語言)的序列化字符。redis字符串中最基礎的get和set命令都是O(1)操做。這使得redis做爲簡單的鍵值存儲及其快速。在思考redis解決方案時,get和set命令使用起來的快速和簡單不容忽視。
對於大多數redis字符串操做來講,訪問和採集命令的時間複雜度要麼是O(1),要麼是O(n)。其中O(n)字符串命令大可能是塊命令,GETRANGE 、MSET、MGET。GETRANGE 命令是一種O(n)操做,其中n爲返回字符串的長度。若是將該操做比做一系列小的get命令(雖然get不返回存儲在鍵中的字符串的子串),則理解起來更直觀。
10.143.128.165:6379> set organization:1 "The British Library" OK 10.143.128.165:6379> GETRANGE organization:1 4 10 British
在該示例中,對於set命令來講 大O符號 +1 ,同時對於getrange 來講 大O符號+6,等價於發送獨立的僞get命令獲取6個字符。
因爲redis將全部數據做爲字符串存儲,特定字符串的類型信息也會被維護起來以支持 INCR/DECR 和BITSTRING 命令。對於 INCR/DECR 命令來講,存儲的值是以10爲基數的64位有符號整數字符串命令。若是該值被其餘諸如APPEND的redis字符串命令修改過,可能會致使破壞。於是以後做用在同一鍵上的與整數相關的redis命令都會失敗。
10.143.128.165:6379> incr new:counter 1 10.143.128.165:6379> get new:counter 1 10.143.128.165:6379> dump new:counter "\x00\xc0\x01\x06\x00\xb0\x95\x8f6$T-o" 10.143.128.165:6379> append new:counter "a" (integer) 2 10.143.128.165:6379> get new:counter "1a" 10.143.128.165:6379> incr new:counter (error) ERR value is not an integer or out of range 10.143.128.165:6379> dump new:counter "\x00\x021a\x06\x00\x8br\x9a\x98-9\x9a\xa6"
將一個或多個字段映射到對應的值的數據結構。
在redis中,全部的哈希值必須是redis字符串,而且有惟一的字段名。字段的值是簡單的redis字符串。
經過調用redis的 HGET 或者 HMGET 命令,同時傳入合適的redis鍵和一到多個字段參數,就能返回字段的值。
對於大多數使用場景,redis哈希爲HSET和HGET命令提供了很棒的 O(1) 性能。與字符串塊命令相似,哈希的HGETALL、HMSET、HMGET、HKEYS、HVALS命令均爲 O(n)。若是哈希很是小,那麼返回全部哈希鍵和值的HGETALL和HMGET命令以前沒有十分明顯的差別。當哈希中鍵和值不斷增加時,二者之間的差別可讓應用程序大不相同。假設哈希中有1000個字段,若是應用程序只是常用其中的300個,對redis調用HGETALL和HVALS的時間複雜度爲O(1000),而使用HMGET的時間複雜度只有O(300)。這是由於雖然HGETALL和HMGET都是 O(n),可是對於 HMGET 其上限爲所請求字段的總和而非整個哈希。哈希的整體較小時,將HMGET替換爲HGETALL是增長redis性能的一種方式。對於大型哈希來講,返回大量值的 HMGET 命令在完成執行前會阻塞其餘客戶端接受數據,從而極大的影響redis的整體性能。在這種狀況下,有針對性的 HGET 會是更好的選擇。
redis哈希的值不能包括哈希、列表 及 其餘數據集合結構,可是redis提供了 HINCRBY 和 HINCRBYFLOAT命令,容許將字段中存儲的字符串值當作整數或者浮點數操做。若是你嘗試更新字段的值 可是弄錯了數據類型,redis會返回錯誤:
10.143.128.165:6379> HMSET weather:2 temperature 46 moisture .001 OK 10.143.128.165:6379> HINCRBY weather:2 temperature -1 (integer) 45 10.143.128.165:6379> HGET weather:2 temperature "45" 10.143.128.165:6379> HINCRBY weather:2 moisture 1 (error) ERR hash value is not an integer 10.143.128.165:6379> HINCRBYFLOAT weather:2 moisture 1 "1.001" 10.143.128.165:6379> HGET weather:2 moisture "1.001"
redis會根據命令來區分設置的值1是整數仍是浮點數。
在redis中列表是字符串的有序集合,它容許重複的字符串值。redis中的列表被更準確地標記和實現爲鏈表。因爲redis列表以鏈表的方式實現的,使用 LPUSH 向列表前端或者 RPUSH 向列表末尾添加條目是相對廉價的操做,表現爲常數時間複雜度 O(1) .對於 LINSERT 和 LSET 命令來講,時間複雜度是線性的 O(n),但二者有些重要的差異。 LSET 能夠指定下標值來設置列表的值。因爲本質上是鏈表,所以變量n是列表的長度,同時無論是設置列表中的第一項仍是最後一項,時間複雜度均爲 O(1)。LINSERT 能夠在參考值以前或者以後插入值,上述操做的時間複雜度爲 O(n)。其中n爲列表元素的個數。該命令必須一致查找直到獲取到參考值,最壞的狀況是將值插入列表的末尾,所以 LINSERT 時間複雜度O(n),即使是特殊狀況下參考值是列表當中第一個元素,使得 LINSERT 命令複雜度爲O(1)。
LRANGE 時間複雜度 O(s+n),s爲從列表的表頭(或表尾)到偏移量位置的元素個數,這取決於列表的大小。n 表明返回的元素總數。若是想要返回整個列表(長度=10),該操做的時間複雜度 O(10+10)。
LTRIM時間複雜度O(n),n爲返回給客戶端的元素數量。
使用 LTRIM 結合 RPUSH 或者 LPUSH,是存儲固定長度的集合的經常使用方法。
示例,只想保存最近7天有價值的平均溫度數據:
10.143.128.165:6379> LPUSH temp:last-seven-days 30 45 50 52 49 55 51 (integer) 7 10.143.128.165:6379> LPUSH temp:last-seven-days 56 (integer) 8 10.143.128.165:6379> LTRIM temp:last-seven-days 0 6 OK 10.143.128.165:6379> LRANGE temp:last-seven-days 0 -1 1) "56" 2) "51" 3) "55" 4) "49" 5) "52" 6) "50" 7) "45"
這種模式容許咱們存儲最近7天的平均溫度,而且當採用這種方法時,因爲每次只有一個值添加到列表中,LTRIM 時間複雜度接近O(1)。
redis中的集合保證了字符串值的惟一性,可是不保證這些值的順序。redis集合實現了集合語義的並集、交集、差集,並在redis實例中將這些集合操做的結果存儲爲一個新的redis集合。以當前的redis集羣的實現來講,並集、交集、差集 這些集合語義受到了諸多限制,而且只能以受限的方式使用。
SADD 將一到多個值添加到集合中,時間複雜度O(n),n爲須要添加到集合的元素總數。
SISMEMBER 用於判斷值是否爲集合的成員,時間複雜度O(1)。
SMEMBERS 返回集合中全部成員的列表,時間複雜度O(n)。
集合可能有着與redis中其餘數據結構類似的性能。在某些狀況下,相較於哈希,集合擁有更佳的內存使用率。
redis中集合特別有用的地方在於對集合 並集、交集、差集操做的支持,全部這些操做有着不一樣的時間複雜度,在redis集羣中使用會受到限制。
SUNION 和 SUNIONSTORE 容許將多個集合的全部成員返回給客戶端或者存儲爲redis中的新集合,時間複雜度O(n),n爲全部集合中元素的總數。
SINTER 和 SINTERSTORE 命令返回集合的交集,後者會將返回的集合存儲在redis中,時間複雜度O(n*m),n是最小集合的大小,m爲集合的總數。
SDIFF 和 SDIFFSTORE 返回或者存儲第一個集合和後續集合之間的差別,時間複雜度O(n),n爲全部集合中元素的總數。
redis中,有序集合數據類型兼備redis列表和集合的特性。集合中的值是有序的,每一個值都是惟一的。
在遊戲中使用單一有序集合能夠記錄玩家得分,ZRANGE或者ZREVRANGE,從排行榜中獲取排名靠前和靠後的玩家。
ZADD 將成員和分值一塊兒添加到有序集合中,時間複雜度 O(log(n)),隨着有序集合的大小的增長,處理時間的增長比率是一個常量。
若是有序集合中全部或部分元素的分值相同,這些值以字典字母順序進行排序,用於文本字符串的字母排序。
將7種顏色添加到一個爲colors的有序集合中:
10.143.128.165:6379> ZADD colors 0 red 0 blue 0 green 0 orange 0 yellow 0 purple 0 pink (integer) 7
如今,經過ZRANGE命令命令將顏色以字母順序取出:
10.143.128.165:6379> ZRANGE colors 0 -1 1) "blue" 2) "green" 3) "orange" 4) "pink" 5) "purple" 6) "red" 7) "yellow"
能夠以ZREVRANGE 以字母倒敘的形式獲取數據:
10.143.128.165:6379> ZREVRANGE colors 0 -1 1) "yellow" 2) "red" 3) "purple" 4) "pink" 5) "orange" 6) "green" 7) "blue"
無論哪一個示例,在colors有序集合中,全部的分值都是相同的。
可使用 ZREVRANGE 命令上帶上 WITHSCORES 關鍵字:
10.143.128.165:6379> ZREVRANGE colors 0 -1 WITHSCORES 1) "yellow" 2) "0" 3) "red" 4) "0" 5) "purple" 6) "0" 7) "pink" 8) "0" 9) "orange" 10) "0" 11) "green" 12) "0" 13) "blue" 14) "0"
LRANGEBYLEX 和 LREVRANGEBYLEX 以字典順序獲取元素,經過特定的語法指定有序集合額起止位置。
10.143.128.165:6379> ZADD myzset 0 a 0 b 0 c 0 d 0 e 0 f 0 g (integer) 7 10.143.128.165:6379> ZRANGEBYLEX myzset - [c 1) "a" 2) "b" 3) "c" 10.143.128.165:6379> ZRANGEBYLEX myzset - (c 1) "a" 2) "b" 10.143.128.165:6379> ZRANGEBYLEX myzset [a (g 1) "a" 2) "b" 3) "c" 4) "d" 5) "e" 6) "f"
當redis使用集羣時,並集和交集的操做只能在有序集合鍵被分片分片到同一哈希槽中,且運行在同一個節點上。
ZINTERSTORE 時間複雜度 O(nk)+O(mlog(m)),n爲最小有序集合的大小,k爲這些求交集的有序集合的總數,m爲最後返回的有序集合計算結果中元素的個數。
ZUNIONSTORE 時間複雜度 O(n)+O(M log(M)),n表明全部有序集合的大小總數,m表明最終有序集合的元素總數。
大型集合和有序集合之間的性能差別 與 是否須要排序無關。
---------------------------------------------------------------------------
redis字符串和對應命令的特殊用法 容許爲redis中相對較少數量的比特使用內存高效的數據結構。
同時,取決於具體的用例場景和數據,使用集合和哈希會提供更好的性能。
在位串中,每一個字節存儲8位,其中位置0處爲最高有效位,它被設置爲0或者1。
redis的位串最大爲512MB,這和redis全部的鍵和值的限制是一致的。
位串如此高效快速的一個緣由是大多數針對它的時間複雜度爲O(1)或O(n)。
使用SETBIT和GETBIT 命令,能夠將位設置爲0或者1,或者獲取值,時間複雜度均爲 O(1) 。
位串對於存儲一系列連續值的二進制信息來講 及其迅速。
BITOP、BITPOS、BITCOUNT,時間複雜度 O(n) ,對位串的使用提供了強大的語義。
位串經常使用的用例場景是 存儲用於表示 一系列順序的鍵的布爾值,即0或者1。
舉例,若是想在網站上追蹤每日的使用狀況,能夠從簡單的「customer:」模式開始,用來爲每位客戶存儲用戶名、哈希過的密碼和電子郵件地址:
10.143.128.165:6379> INCR global:customer (integer) 2445 10.143.128.165:6379> HMSET global:customer:2445 username mmaxwell password '49dffdfsdfdfd' email mmaxwell@gmail.com OK
假設顧客計數從0開始,顧客mmaxwell是連續第2445位顧客。如今,爲了記錄mmaxwell在2016-02-11 訪問了咱們的網站,咱們會設置 2016/02/11:usage 位串的第2445位位,以下:
10.143.128.165:6379> SETBIT 2016/02/11:usage 2445 1
若是咱們想查看mmaxwell是否在那天訪問了咱們的網站,能夠經過GETBIT命令獲取存儲在2445上位的值:
10.143.128.165:6379> GETBIT 2016/02/11:usage 2445 (integer) 1
查找2月11號當天的網站顧客訪問統計能夠簡單地經過 BITCOUNT 命令達成:
10.143.128.165:6379> BITCOUNT 2016/02/11:usage (integer) 365
在2月的這一天,咱們共有365位客戶訪問。
假設咱們正在跟蹤每週顧客的使用狀況,可使用 BITOP 命令和 OR 操做,根據多個位串生成使用狀況,統計的結果存儲在新的鍵中:
10.143.128.165:6379> BITOP OR 2016/02/week2:usage 2016/02/07:usage 2016/02/08:usage 2016/02/09:usage 2016/02/10:usage 2016/02/11:usage 2016/02/12:usage 2016/02/13:usage (integer) 306 10.143.128.165:6379> BITCOUNT 2016/02/week2:usage (integer) 4
爲了計算月度總計並將結果存儲在新的鍵 2016/02:usage 中,能夠再次執行 BITOP 命令:
10.143.128.165:6379> BITOP OR 2016/02:usage 2016/02/week2:usage 2016/02/week3:usage (integer) 306 10.143.128.165:6379> BITCOUNT 2016/02:usage (integer) 7
最後,整個網站的年度總計 能夠針對12個月的位串再次調用BITOP OR操做:
10.143.128.165:6379> BITOP OR 2016:usage 2016/02:usage (integer) 306 10.143.128.165:6379> BITCOUNT 2016:usage (integer) 7
最新的redis數據類型是一個機率數據結構,用來對集合中的惟一項作估計總數。
使用 PFADD 將一到多個元素添加到 HyperLogLogs 中的時間複雜度爲O(1) ,
經過PFCOUNT 獲取單個HyperLogLogs中惟一元素的總計,時間複雜度也是O(1)。
PFCOUNT 計算多個 HyperLogLogs 中元素惟一的總計,性能爲O(n),n表明鍵的總數。
待續 P61