【Redis的那些事 · 上篇】Redis的介紹、五種資料結構演示和分散式鎖

WeskyNet發表於2021-12-18

 

Redis是什麼

Redis,全稱是Remote Dictionary Service,翻譯過來就是,遠端字典服務。

redis屬於nosql非關係型資料庫。Nosql常見的資料關係,基本上是以key-value鍵值對形式存在的。

Key-value: 就像翻閱中文字典或者單詞字典,通過指定的需要查詢的字或者單詞(key),可以查詢到字典裡面對應的詳細內容和介紹(value)

 

Redis的一些特點:支援資料持久化、支援多種資料結構、支援資料備份、原子性操作等。

原子性:操作不能被中途打斷。

 

Redis的由來

Redis的作者:義大利人 —— Salvatore Sanfilippo,現在至少四十幾歲了,還在寫程式碼。

Redis靈感來源:Alessia Merz,義大利一個舞者女郎。Merz在義大利有愚蠢的含義(俚語)。於是,Redis的預設服務埠號6379的來源靈感,來自於Mers這個詞,詳情可看九宮格輸入法:

 

  

 

Redis的安裝

Mac系統:brew install redis

Linux系列系統:apt-get install redis  或 yum install redis 或apt-get install redis-server 或 yum install redis-server

 

 

 

Windows系統:下載地址:https://github.com/tporadowski/redis/releases

 

 

 

 

 

Redis啟動方式

Mac/Linux: 啟動服務端redis-server  啟動客戶端:redis-cli   

如果需要後臺啟動,需要修改 redis.conf  檔案,設定daemonize 為 yes

然後使用 redis-server /xxx/redis.conf 指定配置檔案進行啟動。xxx是指定的路徑。

 

以下下載的姿勢可能不對,版本有點低,所以後面暫且用windows環境下的進行測試。

 

 

 

Windows啟動方式:雙擊redis-server.exe檔案即可執行

 

 

 

可以點選cli.exe檔案,啟動客戶端。

輸入ping,返回pong,代表服務是通的。

通過使用:set key value

可以用來設定一個鍵值對。

通過:get key

可以獲取到key對應的value值。

 

 

通過命令建立redis密碼: config set requirepass 密碼

 

 

通過使用 命令:auth 密碼

進行redis許可權驗證。

使用:keys * 可以顯示所有當前存在的key

 

 

 

使用命令: select index 

可以選擇指定的Redis的Index(資料庫)。Redis預設有最多16個資料庫(或者叫Index),預設從0開始。例如上面設定的預設是0庫,選擇1庫進行查詢,就會沒有東西。

 

 

 

Redis的資料結構

Redis的資料結構,體現在key-value的value上。Key預設都是字串,value的基本資料結構包括字串(string)、列表(list)、雜湊(hash)、集合(set)、有序集合(zset)

 

字串資料結構

字串在redis裡面是可變的。用一個圖來簡單說明一下。

 

 

 

字串儲存規則:Redis儲存字串期間,額外的空間分配規則是,當資料小於1MB的時候,每次擴容的空間是成倍增長的。大於1MB的時候,每次擴容的空間是1MB。

上面這段話如果不太理解,可以看Redis原始碼,原始碼內容如下。

 

 

 

並且String單個資料最大的長度為 2^32-1=512M

關於字串的其他操作:

使用命令: exists key

可以檢視是否存在該key;

使用命令:del key

可以直接刪除指定的key以及對應的value。

 

 

如果已有key,使用:set key xxx

會直接把key原有的值設定為xxx

 

 

使用命令: expire key second

可以給指定的key設定過期時間。例如我設定了10s過期,十秒以後,就會被自動銷燬了。

 

 

 

使用命令: setex  key  second  value

可以設定key-value鍵值對,並且可以同時設定過期時間的秒數。

 

 

 

使用命令: ttl key

可以檢視指定的key的剩餘的過期時間。

 

 

 

對於數值型的字串,可以使用命令:incr key 和 decr key 進行自增1和自減1

使用命令:incrby key number 和 decrby key number 進行自增或自減指定的數值。

 

 

 

可以通過批量設定命令:mset key value key value…… 

進行批量設定。

通過:mget key key key……

進行批量讀取。不過mget批量讀取的結果集是個列表(因為帶有序號)

 

 

 

列表資料結構

Redis的列表,最大可以儲存40億+個元素(2^32-1)。

列表的插入速度很快,時間複雜度是O,但是當資料量特別龐大的時候,使用索引進行查詢操作會變得很慢,因為通過索引定位查詢的時間複雜度為O(n)。

設定列表的key和value命令:lpush key value value value ……

可以設定一個key,帶有多個元素的列表。l:left,代表的是左邊,相當於每個元素是從左邊被寫入的(倒序插入)。

使用命令: lpop  key

可以取出最左邊的元素的值,同時會把該值捨棄掉。 

 

 

 

rpush是依次從右邊插入(正序插入),rpop是取出最右邊的元素的值,然後捨棄掉。r: right,代表右邊

 

 

 

可以使用命令:linsert key before|after 指定的value 要插入的value

進行插入元素。before 會把要插入的元素插入到指定的value的前面;after會把要插入的元素插入到指定的value的後面。

 

 

通過使用命令:lset key index 新的value

可以把列表指定的索引對應的值給替換掉。

 

 

 

可以通過命令:lindex key index

獲取指定的索引的值,並且不會被捨棄。操作索引期間,需要注意時間複雜度,元素多的情況下慎用。

 

 

 

可以使用命令:lrange key 起始索引 結束索引

獲取在索引區間的所有元素。元素包含起始索引和結束索引的值。

 

 

 

列表還可以用來當作訊息佇列使用,因為列表存取的一些方式,可以用來先進先出、先進後出等堆疊操作,先進先出與訊息佇列機制雷同。

 

雜湊資料結構

雜湊資料結構,可以當作是字典(key-value)裡面巢狀了個字典(value資料型別又是一個 key-value的結構)。類似Json,或者類似俄羅斯套娃,例如:

person:{

 “Name”:”wesky”,

  “age”:18

}

 

使用命令: hset  key field value

可以設定雜湊資料結構的key,以及一個屬性和屬性對應的值。

使用命令:hget key field

可以獲取指定雜湊資料的key對應的屬性的值。

使用命令:hmset key field value field value ……

可以批量設定雜湊資料指定key的多個屬性和值。

使用命令:hmget key field1 field2 ……

可以批量獲取指定的key下指定的多個屬性的值。

使用命令:hgetall key

可以獲取指定的雜湊資料的key下的所有屬性和值的列表。如下圖所示。

 

 

 

使用命令:hkeys key

可以獲取雜湊資料指定key的所有屬性名稱的列表;

使用命令:hvals key

可以獲取雜湊資料指定key的所有屬性的值的列表;

使用命令: hlen key

可以獲取到雜湊資料裡面指定key的屬性個數。

 

 

 

集合資料結構

集合結構也可以看成是一個沒有屬性值的雜湊資料結構,並且屬性不能重複且無序的。

類似於:

Person{

 “name”,

 “age”

}

 

使用命令: sadd key field1 field2……

可以設定集合的key和元素集。由於集合是不可重複的,所以重複新增的元素會被自動剔除。

 

 

使用命令:smembers key

可以返回指定集合的所有元素;

使用命令:scard key

可以查詢集合元素的個數;

使用命令:srandmember key (number:可選)

可以隨機返回指定集合的一個或多個元素。不指定個數,即返回一個。

 

 

 

集合資料,可以進行一些集合運算操作。

命令:sdiff  key1  key2

可以比較集合key1和集合key2的差集,差集結果為寫在前面的集合元素減去後面集合的元素;

命令:sinter key1 key2

可以獲取到集合key1和集合key2的交集。

 

 

命令:sunion key1 key2

可以獲取集合key1和集合key2的並集。

 

 

有序集合

有序集合比較常見的一個場景,是用來做排行榜。

命令:zadd  key  score1(分數,用於排行的值)  member1(集合的元素)  score2(分數,用於排行的值)  member2(集合的元素) ……

可以用來新增有序集合。其中,分數代表權重,值越低,排越前。

命令:zrange key 起始索引 結束索引

可以查詢指定集合索引區間的所有元素的屬性。

命令: zincrby key 增加權重值 menber

可以對有序集合指定的元素進行增加權重(對分數進行增加指定的值)

 

 

 

命令:zcard  key

可以獲取有序集合的個數;

命令: zcount  key  最小分數  最大分數

可以獲取到有序集合在指定的分數區間的所有元素;

命令:zcount key member

可以獲取有序集合裡面指定的元素當前的分數;

命令:zrange key  起始索引 結束索引 withscores

可以獲取到有序索引裡面指定的索引區間內所有的元素以及元素對應的分數。

 

 

 

備註:以上五種資料結構,都屬於容器型,它們的特點是,當沒有元素的時候,會被自動釋放掉。

 

 

Redis分散式鎖

Redis的操作是原子性的,如果存在多客戶端同時操作的情況下,會發生一些干擾問題。原子性指的是,redis在進行讀寫期間是不會被打斷的,會一直進行到底。下面用一個圖片進行說明。

 

 

 

如上圖所示,A和B同時都要操作Redis資料庫裡面的Key1。假設此刻Key1儲存的是銀行的存款,然後在A的地方消費掉了,此刻A觸發了扣減餘額的操作。這個時候,修改redis的值是通過先讀取值出來到記憶體裡面,然後進行扣減的;讀取出來的時候,還沒扣減完成,這個時候B(比如說是信用卡自動還款扣錢)也要扣減Key1的餘額,也要進行先讀取出來,然後才進行扣減。由於Redis是原子性操作,所以A的步驟不會被打斷,B也不會被打斷。這個時候,A扣減完成了,例如原本餘額是100元,扣減了10元,A更改完畢以後,值變成了90元。此刻,B也要扣減,例如扣減20元,但是讀取的是A改完之前的值,所以改完以後是80元。以上就產生了衝突,於是就有了Redis的分散式鎖用來避免這個問題。

 

 

 

通過命令: set  key  value  ex  second  nx

可以設定一個鎖,key代表鎖的名稱,value是值;second是鎖的超時時間。

如下圖所示,我開了兩個客戶端,並且標註了我的操作順序號。

 

 

鎖如果沒有過期或刪除,其他客戶端建立鎖會失敗;但是其他客戶端也可以刪除鎖,所以具有一定風險。建議可以對鎖設定不同客戶端所需要的不同的值用來區分。然後把需要操作的地方,放到鎖裡面操作,來避免產生的同時操作產生的問題。

例如虛擬碼:

If(exists(lock))
{

  return false; // 存在鎖,修改失敗

}

Else
{ Set lock true ex 5 nx; Set key1 100; del lock; Return true; // 修改成功 }

  

 

 

今天暫且寫到這兒了,後續還有redis的點陣圖、布隆過濾器、限流、執行緒模型、通訊協議、訂閱模式、管道、記憶體回收、原始碼解讀等等內容,敬請期待~~

 

今天2021-12-18剛好也是自己生日(農曆11月15),祝自己生日快樂。同時也祝大家學習愉快~~

 

歡迎各位大佬留下寶貴意見,歡迎點贊、推薦、或者留言~~ 感謝觀看!

 

 

 

相關文章