天天看點

《Redis實戰》一1.2 Redis資料結構簡介

本節書摘來異步社群《redis實戰》一書中的第1章,第1.2節,作者: 【美】josiah l. carlson(約西亞 l.卡爾森)譯者: 黃健宏 責編: 楊海玲,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

正如之前的表1-1所示,redis可以存儲鍵與5種不同資料結構類型之間的映射,這5種資料結構類型分别為string(字元串)、list(清單)、set(集合)、hash(散列)和zset(有序集合)。有一部分redis指令對于這5種結構都是通用的,如del、type、rename等;但也有一部分redis指令隻能對特定的一種或者兩種結構使用,第3章将對redis提供的指令進行更深入的介紹。

大部分程式員應該都不會對redis的string、list、hash這3種結構感到陌生,因為它們和很多程式設計語言内建的字元串、清單和散列等結構在實作和語義(semantics)方面都非常相似。有些程式設計語言還有集合資料結構,在實作和語義上類似于redis的set。zset在某種程度上是一種redis特有的結構,但是當你熟悉了它之後,就會發現它也是一種非常有用的結構。表1-2對比了redis提供的5種結構,說明了這些結構存儲的值,并簡單介紹了它們的語義。

《Redis實戰》一1.2 Redis資料結構簡介

這一節将介紹如何表示redis的這5種結構,并且還會介紹redis指令的使用方法,進而為本書的後續内容打好基礎。本書展示的所有示例代碼都是用python寫的,如果讀者已經按照附錄a裡面描述的方法安裝好了redis,那麼應該也已經安裝好了python,以及在python裡面使用redis所需的用戶端庫。隻要讀者在電腦裡面安裝了redis、python和redis-py庫,就可以在閱讀本書的同時,嘗試執行書中展示的示例代碼了。

如果讀者熟悉過程式程式設計語言或者面向對象程式設計語言,那麼即使沒有使用過python,應該也可以看懂python代碼。另一方面,如果讀者決定使用其他程式設計語言來操作redis,那麼就需要自己來将本書的python代碼翻譯成正在使用的語言的代碼。

為了讓示例代碼盡可能地簡單,本書會盡量避免使用python的進階特性,并使用函數而不是類或者其他東西來執行redis操作,以此來将焦點放在使用redis解決問題上面,而不必過多地關注python的文法。本節将使用redis-cli控制台與redis進行互動。首先,讓我們來了解一下redis中最簡單的結構:string。

redis的string和其他程式設計語言或者其他鍵值存儲提供的字元串非常相似。本書在使用圖檔表示鍵和值的時候,通常會将鍵名(key name)和值的類型放在方框的頂部,并将值放在方框的裡面。圖1-1以鍵為hello、值為world的string為例,分别标記了方框的各個部分。

《Redis實戰》一1.2 Redis資料結構簡介

string擁有一些和其他鍵值存儲相似的指令,比如get(擷取值)、set(設定值)和del(删除值)。如果讀者已經按照附錄a中給出的方法安裝了redis,那麼可以根據代碼清單1-1展示的例子,嘗試使用redis-cli執行set、get和del,表1-3描述了這3個指令的基本用法。

《Redis實戰》一1.2 Redis資料結構簡介
《Redis實戰》一1.2 Redis資料結構簡介

使用 redis-cli 為了讓讀者在一開始就能便捷地與 redis 進行互動,本章将使用redis-cli這個互動式用戶端來介紹redis指令。

除了能夠get、set和del字元串值之外,redis還提供了一些可以對字元串的其中一部分内容進行讀取和寫入的指令,以及一些能對字元串存儲的數值執行自增或者自減操作的指令。第3章将對這些指令進行介紹,但是在此之前,我們還有許多基礎知識需要了解,下面來看一下redis的清單及其功能。

1.2.2 redis中的清單

redis對連結清單(linked-list)結構的支援使得它在鍵值存儲的世界中獨樹一幟。一個清單結構可以有序地存儲多個字元串,和表示字元串時使用的方法一樣,本節使用帶有标簽的方框來表示清單,并将清單包含的元素放在方框裡面。圖1-2展示了一個這樣的示例。

《Redis實戰》一1.2 Redis資料結構簡介

redis清單可執行的操作和很多程式設計語言裡面的清單操作非常相似:lpush指令和rpush指令分别用于将元素推入清單的左端(left end)和右端(right end);lpop指令和rpop指令分别用于從清單的左端和右端彈出元素;lindex指令用于擷取清單在給定位置上的一個元素;lrange指令用于擷取清單在給定範圍上的所有元素。代碼清單1-2展示了一些清單指令的使用示例,表1-4簡單介紹了示例中用到的各個指令。

《Redis實戰》一1.2 Redis資料結構簡介
《Redis實戰》一1.2 Redis資料結構簡介

即使redis的清單隻支援以上提到的幾個指令,它也已經可以用來解決很多問題了,但redis并沒有就此止步——除了上面提到的指令之外,redis清單還擁有從清單裡面移除元素的指令、将元素插入清單中間的指令、将清單修剪至指定長度(相當于從清單的其中一端或者兩端移除元素)的指令,以及其他一些指令。第3章将介紹許多清單指令,但是在此之前,讓我們先來了解一下redis的集合。

redis 的集合和清單都可以存儲多個字元串,它們之間的不同在于,清單可以存儲多個相同的字元串,而集合則通過使用散清單來保證自己存儲的每個字元串都是各不相同的(這些散清單隻有鍵,但沒有與鍵相關聯的值)。本書表示集合的方法和表示清單的方法基本相同,圖1-3展示了一個包含3個元素的示例集合。

《Redis實戰》一1.2 Redis資料結構簡介

因為redis的集合使用無序(unordered)方式存儲元素,是以使用者不能像使用清單那樣,将元素推入集合的某一端,或者從集合的某一端彈出元素。不過使用者可以使用sadd指令将元素添加到集合,或者使用sram指令從集合裡面移除元素。另外還可以通過sismember指令快速地檢查一個元素是否已經存在于集合中,或者使用smembers指令擷取集合包含的所有元素(如果集合包含的元素非常多,那麼smembers指令的執行速度可能會很慢,是以請謹慎地使用這個指令)。代碼清單1-3展示了一些集合指令的使用示例,表1-5簡單介紹了代碼清單裡面用到的各個指令。

代碼清單1-3 sadd、smembers、sismember和srem的使用示例

《Redis實戰》一1.2 Redis資料結構簡介
《Redis實戰》一1.2 Redis資料結構簡介

跟字元串和清單一樣,集合除了基本的添加操作和移除操作之外,還支援很多其他操作,比如sinter、sunion、sdiff這3個指令就可以分别執行常見的交集計算、并集計算和差集計算。第3章将對集合的相關指令進行更詳細的介紹,另外第7章還會展示如何使用集合來解決多個問題。不過别心急,因為在redis提供的5種資料結構中,還有兩種我們尚未了解,讓我們先來看看redis的散列。

redis的散列可以存儲多個鍵值對之間的映射。和字元串一樣,散列存儲的值既可以是字元串又可以是數字值,并且使用者同樣可以對散列存儲的數字值執行自增操作或者自減操作。圖1-4展示了一個包含兩個鍵值對的散列。

《Redis實戰》一1.2 Redis資料結構簡介

散列在很多方面就像是一個微縮版的redis,不少字元串指令都有相應的散列版本。代碼清單1-4展示了怎樣對散列執行插入元素、擷取元素和移除元素等操作,表1-6簡單介紹了代碼清單裡面用到的各個指令。

代碼清單1-4 hset、hget、hgetall和hdel的使用示例

《Redis實戰》一1.2 Redis資料結構簡介
《Redis實戰》一1.2 Redis資料結構簡介

熟悉文檔資料庫的讀者可以将redis的散列看作是文檔資料庫裡面的文檔,而熟悉關系資料庫的讀者則可以将redis的散列看作是關系資料庫裡面的行,因為散列、文檔和行這三者都允許使用者同時通路或者修改一個或多個域(field)。最後,讓我們來了解一下redis的5種資料結構中的最後一種:有序集合。

有序集合和散列一樣,都用于存儲鍵值對:有序集合的鍵被稱為成員(member),每個成員都是獨一無二的;而有序集合的值則被稱為分值(score),分值必須為浮點數。有序集合是redis裡面唯一一個既可以根據成員通路元素(這一點和散列一樣),又可以根據分值以及分值的排列順序來通路元素的結構。圖1-5展示了一個包含兩個元素的有序集合示例。

《Redis實戰》一1.2 Redis資料結構簡介

和redis的其他結構一樣,使用者可以對有序集合執行添加、移除和擷取等操作,代碼清單1-5展示了這些操作的執行示例,表1-7簡單介紹了代碼清單裡面用到的各個指令。

代碼清單1-5 zadd、zrange、zrangebyscore和zrem的使用示例

《Redis實戰》一1.2 Redis資料結構簡介
《Redis實戰》一1.2 Redis資料結構簡介

現在讀者應該已經知道有序集合是什麼和它能幹什麼了,到目前為止,我們基本了解了redis提供的5種結構。接下來的一節将展示如何通過結合散列的資料存儲能力和有序集合内建的排序能力來解決一個常見的問題。