Redis的3個高級數據結構

2021-02-19 朱小廝的博客

平常我們我接觸最多的是5個入門級數據結構:String,Hash,List,Set,Sorted Set。本文介紹3個高級數據結構:Bitmaps,Hyperloglogs,GEO。

Bitmaps

bitmaps不是一個真實的數據結構。而是String類型上的一組面向bit操作的集合。由於strings是二進位安全的blob,並且它們的最大長度是512m,所以bitmaps能最大設置2^32個不同的bit。

bit操作被分為兩組:

Bitmaps的最大優點就是存儲信息時可以節省大量的空間。例如在一個系統中,不同的用戶被一個增長的用戶ID表示。40億(2^32=4*1024*1024*1024≈40億)用戶只需要512M內存就能記住某種信息,例如用戶是否登錄過。

Bits設置和獲取通過SETBIT 和GETBIT 命令,用法如下:

SETBIT key offset value
GETBIT key offset

使用實例:

127.0.0.1:6380> setbit dupcheck 10 1
(integer) 0
127.0.0.1:6380> getbit dupcheck 10 
(integer) 1

SETBIT命令第一個參數是位編號,第二個參數是這個位的值,只能是0或者1。如果bit地址超過當前string長度,會自動增大string。

Bitmaps示意圖

GETBIT命令指示返回指定位置bit的值。超過範圍(尋址地址在目標key的string長度以外的位)的GETBIT總是返回0。三個操作bits組的命令如下:

bitmaps一般的使用場景:

例如,想像一下你想知道訪問你的網站的用戶的最長連續時間。你開始計算從0開始的天數,就是你的網站公開的那天,每次用戶訪問網站時通過SETBIT命令設置bit為1,可以簡單的用當前時間減去初始時間並除以3600*24(結果就是你的網站公開的第幾天)當做這個bit的位置。

這種方法對於每個用戶,都有存儲每天的訪問信息的一個很小的string字符串。通過BITCOUN就能輕易統計某個用戶連續訪問網站的天數。另外通過調用BITPOS命令,或者客戶端獲取並分析這個bitmap,就能計算出最長停留時間。

HyperLogLogs

HyperLogLog是用於計算唯一事物的概率數據結構(從技術上講,這被稱為估計集合的基數)。如果統計唯一項,項目越多,需要的內存就越多。因為需要記住過去已經看過的項,從而避免多次統計這些項。

然而,有一組算法可以交換內存以獲得精確度:在redis的實現中,您使用標準錯誤小於1%的估計度量結束。這個算法的神奇在於不再需要與需要統計的項相對應的內存,取而代之,使用的內存一直恆定不變。最壞的情況下只需要12k,就可以計算接近2^64個不同元素的基數。或者如果您的HyperLogLog(我們從現在開始簡稱它為HLL)已經看到的元素非常少,則需要的內存要要少得多。

在redis中HLL是一個不同的數據結構,它被編碼成Redis字符串。因此可以通過調用GET命令序列化一個HLL,也可以通過調用SET命令將其反序列化到redis伺服器。

HLL的API類似使用SETS數據結構做相同的任務,SETS結構中,通過SADD命令把每一個觀察的元素添加到一個SET集合,用SCARD命令檢查SET集合中元素的數量,集合裡的元素都是唯一的,已經存在的元素不會被重複添加。

而使用HLL時並不是真正添加項到HLL中(這一點和SETS結構差異很大),因為HLL的數據結構只包含一個不包含實際元素的狀態,API是一樣的:

127.0.0.1:6380> PFADD hll a b c d d c
(integer) 1
127.0.0.1:6380> PFCOUNT hll
(integer) 4
127.0.0.1:6380> PFADD hll e
(integer) 1
127.0.0.1:6380> PFCOUNT hll
(integer) 5

PFMERGE命令說明:

PFMERGE destkey sourcekey [sourcekey ...]
Merge N different HyperLogLogs into a single one.

用法(把hll1和hll2合併到hlls中):

127.0.0.1:6380> PFADD hll1 1 2 3
(integer) 1
127.0.0.1:6380> PFADD hll2 3 4 5
(integer) 1
127.0.0.1:6380> PFMERGE hlls hll1 hll2
OK
127.0.0.1:6380> PFCOUNT hlls

HLL數據結構的一個使用場景就是計算用戶每天在搜索框中執行的唯一查詢,即搜索頁面UV統計。而Bitmaps則用於判斷某個用戶是否訪問過搜索頁面。這是它們用法的不同。

GEO

Redis的GEO特性在 Redis3.2版本中推出,這個功能可以將用戶給定的地理位置(經度和緯度)信息儲存起來,並對這些信息進行操作。GEO相關命令只有6個:

經緯度具體的限制,由EPSG:900913/EPSG:3785/OSGEO:41001規定如下:
有效的經度從-180度到180度。
有效的緯度從-85.05112878度到85.05112878度。
當坐標位置超出上述指定範圍時,該命令將會返回一個錯誤。

GEOHASH:GEOHASH key member [member …],返回一個或多個位置元素的標準Geohash值,它可以在http://geohash.org/使用。查詢例子:http://geohash.org/sqdtr74hyu0.(可以通過谷歌了解Geohash原理,或者戳Geohash基本原理:https://www.cnblogs.com/tgzhu/p/6204173.html)。

GEOPOS:GEOPOS key member [member …],從key裡返回所有給定位置元素的位置(經度和緯度)。

GEODIST:GEODIST key member1 member2 [unit],返回兩個給定位置之間的距離。GEODIST命令在計算距離時會假設地球為完美的球形。在極限情況下,這一假設最大會造成0.5%的誤差。

指定單位的參數unit必須是以下單位的其中一個:
m 表示單位為米(默認)。
km 表示單位為千米。
mi 表示單位為英裡。
ft 表示單位為英尺。

GEORADIUS:GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count],以給定的經緯度為中心, 返回鍵包含的位置元素當中, 與中心的距離不超過給定最大距離的所有位置元素。這個命令可以查詢某城市的周邊城市群。

GEORADIUSBYMEMBER:GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count],這個命令和GEORADIUS命令一樣,都可以找出位於指定範圍內的元素,但是GEORADIUSBYMEMBER的中心點是由給定的位置元素決定的,而不是像 GEORADIUS那樣,使用輸入的經度和緯度來決定中心點。

指定成員的位置被用作查詢的中心。

GEO的6個命令用法示例如下:

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEOHASH Sicily Palermo Catania
1) "sqc8b49rny0"
2) "sqdtr74hyu0"

redis> GEOPOS Sicily Palermo Catania NonExisting
1) 1) "13.361389338970184"
   2) "38.115556395496299"
2) 1) "15.087267458438873"
   2) "37.50266842333162"
3) (nil)

redis> GEODIST Sicily Palermo Catania
"166274.15156960039"

redis> GEORADIUS Sicily 15 37 100 km
1) "Catania"
redis> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"

redis> GEORADIUSBYMEMBER Sicily Agrigento 100 km
1) "Agrigento"
2) "Palermo"

相關焦點

  • 圖解redis五種數據結構底層實現(動圖哦)
    redis有五種基本數據結構:字符串、hash、set、zset、list。但是你知道構成這五種結構的底層數據結構是怎樣的嗎? 今天我們來花費五分鐘的時間了解一下。 (目前redis版本為3.0.6)動態字符串SDSSDS是"simple dynamic string"的縮寫。
  • 二進位跳動帶你看Redis數據結構底層
    一場面試至少也是半小時起,如果一個問題你只能回答不到50個字,這個結果肯定不是面試官想要的,其實也不是你自己想要的。緊接著還有問題,String在redis底層是怎麼存儲的?這些數據類型在Redis中是怎麼存放的?Redis快的原因是不是只有單線程和基於內存處理?
  • Streams:深入剖析Redis5.0全新數據結構
    Redis 5.0 全新的數據類型:streams,官方把它定義為:以更抽象的方式建模日誌的數據結構。Redis的streams主要是一個append only的數據結構,至少在概念上它是一種在內存中表示的抽象數據類型,只不過它們實現了更強大的操作,以克服日誌文件本身的限制。如果你了解MQ,那麼可以把streams當做MQ。
  • 還不懂Redis是什麼?一文帶你深入Redis基本結構,準備向開發進軍
    也可以說,對Redis 地了解和應用實踐已成為當下中高級後端開發者繞不開的必備技能。Redis安裝體驗Redis需要使用Linux或者Mac環境,如果是Windows可以考慮使用虛擬機。〉yum install redis#運行客戶端> redis-cliRedis基礎數據結構Redis有5種基礎數據結構,分別為: string (字符串)、list (列表)、set (集合)、hash (哈希)和zset
  • redis五大數據類型使用場景
    Redis是一種基於鍵值對的NoSQL資料庫,它的值主要由string(字符串),hash(哈希),list(列表),set(集合),zset(有序集合)五種基本數據結構構成,除此之外還支持一些其他的數據結構和算法。key都是由字符串構成的,那麼這五種數據結構的使用場景有哪些?一起來看看!
  • Redis入門教程:特性及數據類型的操作
    Redis提供了一些豐富的數據結構,包括 lists, sets, ordered sets 以及 hashes ,當然還有和Memcached一樣的 strings結構.Redis當然還包括了對這些數據結構的豐富操作。  2、Redis的優點  性能極高 – Redis能支持超過 100K+ 每秒的讀寫頻率。
  • 《Redis入門指南》第1集:Redis的5種數據類型
    持久化存儲跟關係資料庫不同,redis的數據是存儲在內存中,這也讓讀取數據的性能更好。那小夥伴要問了,一斷電,內存中的數據都丟了咋整?上面說完了持久化存儲,下面我們開始講redis的5個數據類型:字符型、散列型、列表型、集合型、有序集合型。
  • 一文搞定Redis五大數據類型及使用場景
    ,除此之外還支持一些其他的數據結構和算法。key都是由字符串構成的,那麼這五種數據結構的使用場景有哪些?一起來看看!web端的大多數請求都是從Redis中獲取的數據,如果Redis中沒有需要的數據,則會從MySQL中去獲取,並將獲取到的數據寫入redis。
  • Redis 內部數據結構詳解(1):dict
    如有好文章投稿,請點擊 → 這裡了解詳情本系列基於 Redis 3.2 分支如果你使用過Redis,一定會像我一樣對它的內部實現產生興趣。比如:dictsdsziplistquicklistskiplist第一個層面的「數據結構」,Redis的官方文檔(http://redis.io/topics/data-types-intro)有詳細的介紹。
  • 從零開始學習大數據系列(六十五) Redis入門及基礎實踐
    關係型資料庫最典型的數據結構是表,由二維表及其之間的聯繫所組成的一個數據組織。缺點:1、讀寫性能比較差,尤其是海量數據的高效率讀寫;2、固定的表結構,靈活度稍欠;3、高並發讀寫需求,傳統關係型資料庫來說,硬碟I/O是一個很大的瓶頸。
  • Redis詳解:sets數據類型及操作
    系列文章:  Redis詳解:strings數據類型及操作  Redis詳解:hashes數據類型及操作  Redis詳解:lists數據類型及操作  Redis的set是string類型的無序集合。set元素最大可以包含(2的32次方)個元素。
  • redis學習(四)鍵空間數據持久化
    上一篇文章學習了redis服務端的核心數據結構,其中就包含redisDB->dict 和redisDB->expire,本文學習持久化也是基於這兩個字典的
  • 【深入學習Redis】Redis內存模型
    3、哈希概況哈希(作為一種數據結構),不僅是redis對外提供的5種對象類型的一種(與字符串、列表、集合、有序結合併列),也是Redis作為Key-Value資料庫所使用的數據結構。ht是一個包含兩個項的數組,每項都指向一個dictht結構,這也是Redis的哈希會有1個dict、2個dictht結構的原因。通常情況下,所有的數據都是存在放dict的ht[0]中,ht[1]只在rehash的時候使用。dict進行rehash操作的時候,將ht[0]中的所有數據rehash到ht[1]中。然後將ht[1]賦值給ht[0],並清空ht[1]。
  • Redis 內部數據結構詳解(2):sds
    如有好文章投稿,請點擊 → 這裡了解詳情本系列基於 Redis 3.2 分支本文是《Redis內部數據結構詳解》系列的第二篇,講述Redis中使用最多的一個基礎數據結構:sds。最後通過getrange取從倒數第5個字節到倒數第1個字節的內容,得到」zhang」。這些命令的實現,有一部分是和sds的實現有關的。下面我們開始詳細討論。sds的數據結構定義我們知道,在C語言中,字符串是以』\0』字符結尾(NULL結束符)的字符數組來存儲的,通常表達為字符指針的形式(char *)。
  • acl 框架中的 Redis 庫已經支持集群版 Redis 3.0
    據 redis 官方網站顯示,支持集群版的 redis3.0 快要發布了(現在已經到了redis3.0 rc4 版本),這樣使用者就不需要自己花很大力氣來針對
  • Redis 內部數據結構詳解(4):ziplist
    如有好文章投稿,請點擊 → 這裡了解詳情本系列基於 Redis 3.2 分支本文是《Redis內部數據結構詳解》系列的第四篇,介紹ziplist。ziplist的數據結構定義ziplist的數據結構組成是本文要討論的重點。實際上,ziplist還是稍微有點複雜的,它複雜的地方就在於它的數據結構定義。一旦理解了數據結構,它的一些操作也就比較容易理解了。我們接下來先從總體上介紹一下ziplist的數據結構定義,然後舉一個實際的例子,通過例子來解釋ziplist的構成。
  • Redis系列-數據類型set
    先給大家提出一個新的存儲需求:存儲大量的數據,在查詢方面提供更高的效率 。來請出我們今天要說的主角set。 可能大家會有個疑問,難道list不能滿足嗎? list也可以存大量數據而且還有順序,還能使用索引訪問,但是list 的存儲結構是鍊表的存儲結構。
  • 五種數據結構
    五種數據結構以下列舉一些常用的操作命令,更多信息可參見官網,Redis 提供了 5 種數據結構,除此之外還有一些通用命令。消息隊列Redis List 結構的 lpush + brpop 命令可實現消息隊列,lpush 命令是從左端插入數據,brpop 命令是從右端阻塞式的讀取數據,阻塞讀過程中如果隊列中沒有數據,會立即進入休眠直到數據到來或超過設置的 timeout 時間,則會立即醒過來。
  • 46道Redis面試題,含參考答案!
    1.memcached 所有的值均是簡單的字符串,redis 作為其替代者,支持更為豐富的數據類型2.redis 的速度比 memcached 快很多 redis 的速度比 memcached 快很多3.redis 可以持久化其數據 redis 可以持久化其數據3、Redis 支持哪幾種數據類型?
  • Python | Python學習之Redis交互詳解
    配置啟動:sudo redis-server /etc/redis/redis.conf查看redis進程:ps-ef|grep redis殺死進程:sudo kill -9 pidredis數據結構與操作redis數據結構redis是key-value的數據結構,每條數據都是一個鍵值對鍵的類型是字符串,且鍵不能重複值的類型分為五種:字符串strin