1. 程式人生 > 資料庫 >Redis實戰之入門到精通,通俗易懂!

Redis實戰之入門到精通,通俗易懂!

本章主要內容
 Redis 與其他軟體的相同之處和不同之處
 Redis 的用法
 使用 Python 示例程式碼與 Redis 進行簡單的互動
 使用 Redis 解決實際問題

以下知識點解析來自於《Redis實戰》文件其中的一部分!由於不影響觀看,只選取了其中的一部分來展示。
需要完整版的可以

Redis 是一個遠端記憶體資料庫,它不僅效能強勁,而且還具有複製特性以及為解決問題而生
的獨一無二的資料模型。Redis 提供了 5 種不同型別的資料結構,各式各樣的問題都可以很自然
地對映到這些資料結構上:Redis 的資料結構致力於幫助使用者解決問題,而不會像其他資料庫那
樣,要求使用者扭曲問題來適應資料庫。除此之外,通過複製、持久化(persistence)和客戶端分

片(client-side sharding)等特性,使用者可以很方便地將 Redis 擴充套件成一個能夠包含數百 GB 資料、
每秒處理上百萬次請求的系統。
筆者第一次使用 Redis 是在一家公司裡面,這家公司需要對一個儲存了 6 萬個客戶聯絡
方式的關係資料庫進行搜尋,搜尋可以根據名字、郵件地址、所在地和電話號碼來進行,每
次搜尋需要花費 10~15 秒的時間。在花了一週時間學習 Redis 的基礎知識之後,我使用 Redis
重寫了一個新的搜尋引擎,然後又花費了數週時間來仔細測試這個新系統,使它達到生產級
別,最終這個新的搜尋系統不僅可以根據名字、郵件地址、所在地和電話號碼等資訊來過濾
和排序客戶聯絡方式,並且每次操作都可以在 50 毫秒之內完成,這比原來的搜尋系統足足快
了 200 倍。閱讀本書可以讓你學到很多小技巧、小竅門以及使用 Redis 解決某些常見問題的
方法。
本章將介紹 Redis 的適用範圍,以及在不同環境中使用 Redis 的方法(比如怎樣跟不同的組
件和程式語言進行通訊等);而之後的章節則會展示各式各樣的問題,以及使用 Redis 來解決這
些問題的方法。

第 1 章 初識 Redis

1.1 Redis 簡介
安裝 Redis 和 Python 附錄 A 介紹了快速安裝 Redis 和 Python 的方法。
在其他程式語言裡面使用 Redis 本書只展示了使用 Python 語言編寫的示例程式碼,使用 Ruby、Java 和 JavaScript(Node.js)編寫的示例程式碼可以在這裡找到:https://github.com/josiahcarlson/redis-in-action。使用 Spring 框架的讀者可以通過檢視 http://www.springsource.org/spring-data/redis來學習如何在 Spring 框架中使用 Redis。

前面對於Redis資料庫的描述只說出了一部分真相。Redis是一個速度非常快的非關係數
據庫(non-relational database),它可以儲存鍵(key)與 5 種不同型別的值(value)之間的
對映(mapping),可以將儲存在記憶體的鍵值對資料持久化到硬碟,可以使用複製特性來擴
展讀效能,還可以使用客戶端分片

1.1.1 Redis 與其他資料庫和軟體的對比
來擴充套件寫效能,接下來的幾節將分別介紹Redis的這幾個特性。
如果你熟悉關係資料庫,那麼你肯定寫過用來關聯兩個表的資料的 SQL 查詢 。而 Redis 則屬於人們常說的 NoSQL 資料庫或者非關係資料庫:Redis 不使用表,它的資料庫也不會預定義或者強制去要求使用者對 Redis 儲存的不同資料進行關聯。

高效能鍵值快取伺服器 memcached 也經常被拿來與 Redis 進行比較:這兩者都可用於儲存鍵值對映,彼此的效能也相差無幾,但是 Redis 能夠自動以兩種不同的方式將資料寫入硬碟,並且 Redis 除了能儲存普通的字串鍵之外,還可以儲存其他 4 種資料結構,而 memcached 只能儲存普通的字串鍵。這些不同之處使得 Redis 可以用於解決更為廣泛的問題,並且既可以用作主資料庫(primary database)使用,又可以作為其他儲存系統的輔助資料庫(auxiliary database)使用。

本書的後續章節會分別介紹將 Redis 用作主儲存(primary storage)和二級儲存(secondary storage)時的用法和查詢模式。一般來說,許多使用者只會在 Redis 的效能或者功能是必要的情況下,才會將資料儲存到 Redis 裡面:如果程式對效能的要求不高,又或者因為費用原因而沒辦法將大量資料儲存到記憶體裡面,那麼使用者可能會選擇使用關係資料庫,或者其他非關係資料庫。在實際中,讀者應該根據自己的需求來決定是否使用 Redis,並考慮是將 Redis 用作主儲存還是輔

① 分片是一種將資料劃分為多個部分的方法,對資料的劃分可以基於鍵包含的 ID、基於鍵的雜湊值,或者
基於以上兩者的某種組合。通過對資料進行分片,使用者可以將資料儲存到多臺機器裡面,也可以從多臺
機器裡面獲取資料,這種方法在解決某些問題時可以獲得線性級別的效能提升。

助儲存,以及如何通過複製、持久化和事務等手段保證資料的完整性。
表 1-1 展示了一部分在功能上與 Redis 有重疊的資料庫伺服器和快取伺服器,從這個表可以
看出 Redis 與這些資料庫及軟體之間的區別。 
在這裡插入圖片描述
1.1.2 附加特性
在使用類似 Redis 這樣的記憶體資料庫時,一個首先要考慮的問題就是“當伺服器被關閉時,伺服器儲存的資料將何去何從呢?”Redis 擁有兩種不同形式的持久化方法,它們都可以用小而緊湊的格式將儲存在記憶體中的資料寫入硬碟:第一種持久化方法為時間點轉儲(point-in-time dump),轉儲操作既可以在“指定時間段內有指定數量的寫操作執行”這一條件被滿足時執行,又可以通過呼叫兩條轉儲到硬碟(dump-to-disk)命令中的任何一條來執行;第二種持久化方法將所有修改了資料庫的命令都寫入一個只追加(append-only)檔案裡面,使用者可以根據資料的重要程度,將只追加寫入設定為從不同步(sync)、每秒同步一次或者每寫入一個命令就同步一次。

我們將在第 4 章中更加深入地討論這些持久化選項。另外,儘管 Redis 的效能很好,但受限於 Redis 的記憶體儲存設計,有時候只使用一臺 Redis伺服器可能沒有辦法處理所有請求。因此,為了擴充套件 Redis 的讀效能,併為 Redis 提供故障轉移

5 (failover)支援 ,Redis 實現了主從複製特性:執行復制的從伺服器會連線上主伺服器,接收主伺服器傳送的整個資料庫的初始副本(copy);之後主伺服器執行的寫命令,都會被髮送給所有連線著的從伺服器去執行,從而實時地更新從伺服器的資料集。因為從伺服器包含的資料會不斷地進行更新,所以客戶端可以向任意一個從伺服器傳送讀請求,以此來避免對主伺服器進行集中式的訪問。我們將在第 4 章中更加深入地討論 Redis 從伺服器。

1.1.3 使用 Redis 的理由
有 memcached 使用經驗的讀者可能知道,使用者只能用 APPEND 命令將資料新增到已有字串的末尾。memcached 的文件中宣告,可以用 APPEND 命令來管理元素列表。這很好!使用者可以將元素追加到一個字串的末尾,並將那個字串當作列表來使用。但隨後如何刪除這些元素呢?memcached 採用的辦法是通過黑名單(blacklist)來隱藏列表裡面的元素,從而避免對元素執行讀取、更新、寫入(包括在一次資料庫查詢之後執行的 memcached 寫入)等操作。相反地,Redis 的 LIST 和 SET 允許使用者直接新增或者刪除元素。使用 Redis 而不是 memcached 來解決問題,不僅可以讓程式碼變得更簡短、更易懂、更易維護,而且還可以使程式碼的執行速度更快(因為使用者不需要通過讀取資料庫來更新資料)。除此之外,在其他許多情況下,Redis 的效率和易用性也比關係資料庫要好得多。

資料庫的一個常見用法是儲存長期的報告資料,並將這些報告資料用作固定時間範圍內的聚合資料(aggregates)。收集聚合資料的常見做法是:先將各個行插入一個報告表裡面,之後再通過掃描這些行來收集聚合資料,並根據收集到的聚合資料來更新聚合表中已有的那些行。之所以使用插入行的方式來儲存,是因為對於大部分資料庫來說,插入行操作的執行速度非常快(插入行只會在硬碟檔案末尾進行寫入)。不過,對錶裡面的行進行更新卻是一個速度相當慢的操作,因為這種更新除了會引起一次隨機讀(random read)之外,還可能會引起一次隨機寫(random write)。而在Redis裡面,使用者可以直接使用原子的(atomic)INCR命令及其變種來計算聚合資料,並且因為Redis將資料儲存在記憶體裡面 ①

① 客觀來講,memcached 也能用在這個簡單的場景裡,但使用 Redis 儲存聚合資料有以下 3 個好處:
1、首先,使用 Redis 可以將彼此相關的聚合資料放在同一個結構裡面,這樣訪問聚合資料就會變得更為容易;
2、其次,使用 Redis 可以將聚合資料放到有序集合裡面,構建出一個實時的排行榜;
3、最後,Redis 的聚合資料可以是整數或者浮點數,而 memcached 的聚合資料只能是整數。而且傳送給Redis的命令請求並不需要經過典型的查詢分析器(parser)或者查詢優化器(optimizer)進行處理,所以對Redis儲存的資料執行隨機寫的速度總是非常迅速的。

使用 Redis 而不是關係資料庫或者其他硬碟儲存資料庫,可以避免寫入不必要的臨時資料,也免去了對臨時資料進行掃描或者刪除的麻煩,並最終改善程式的效能。雖然上面列舉的都是一些簡單的例子,但它們很好地證明了“工具會極大地改變人們解決問題的方式”這一點。

1.2 Redis 資料結構簡介

正如之前的表 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 種結構,說明了這些結構儲存的值,並簡單介紹了
它們的語義。
在這裡插入圖片描述

命令列表 本節在介紹每個資料型別的時候,都會在一個表格裡面展示一小部分處理這些資料結 構的命令,之後的第 3會展示一個更詳細(但仍不完整)的命令列表,完整的 Redis 命令列表 可以http://redis.io/commands 找到。

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

請安裝 Redis 和 Python 在閱讀後續內容之前,請讀者先按照附錄 A 中介紹的方法安裝 Redis 和Python。如果讀者覺得附錄 A 描述的安裝方法過於複雜,那麼這裡有一個更簡單的方法,但這 個方法只能用於 Debian系統(或者該系統的衍生系統):從 http://redis.io/download 下載 Redis 的 壓縮包,解壓壓縮包,執行 make&& sudo make install,之後再執行 sudo python -m easy_install redis hiredis(hiredis 是可選的,它是一個使用 C 語言編寫的高效能 Redis 客戶端)。

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

使用其他語言編寫的示例程式碼 儘管沒有包含在書中,但本書展示的 Python 示例程式碼已經被翻譯成 了 Ruby 程式碼、Java 程式碼和JavaScript 程式碼,這些翻譯程式碼可以在 https://github.com/josiahcarlson/redis-in-action 下載到。跟 Python 編寫的示例程式碼一樣,這些翻譯程式碼也包含相應的註釋,方便讀 者參考。

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

1.2.1 Redis 中的字串

Redis 的字串和其他程式語言或者其他鍵值儲存提供的字串非常相似。本書在使用
圖片表示鍵和值的時候,通常會將鍵名(key name)和值的型別放在方框的頂部,並將值
放在方框的裡面。圖 1-1 以鍵為 hello、值為 world 的字串為例,分別標記了方框的各
個部分。

在這裡插入圖片描述
字串擁有一些和其他鍵值儲存相似的命令,比如 GET(獲取值)、SET(設定值)和 DEL(刪除值)。如果讀者已經按照附錄 A 中給出的方法安裝了 Redis,那麼可以根據程式碼清單 1-1 展示的例子,嘗試使用 redis-cli 執行 SET、GET 和 DEL,表 1-3 描述了這 3 個命令的基本用法。
在這裡插入圖片描述

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

除了能夠 GET、SET 和 DEL 字串值之外,Redis 還提供了一些可以對字串的其中一部分內容進行讀取和寫入的命令,以及一些能對字串儲存的數值執行自增或者自減操作的命令。第 3 章
將對這些命令進行介紹,但是在此之前,我們還有許多基礎知識需要了解,下面來看一下 Redis 的列表及其功能。

1.2.2 Redis 中的列表
Redis 對連結串列(linked-list)結構的支援使得它在鍵值儲存的世界中獨樹一幟。一個列表結構可以有序地儲存多個字串,和表示字串時使用的方法一樣,本節使用帶有標籤的方框來表示列表,並將列表包含的元素放在方框裡面。圖 1-2 展示了一個這樣的示例。
在這裡插入圖片描述

Redis 列表可執行的操作和很多程式語言裡面的列表操作非常相似:LPUSH 命令和 RPUSH 命令分別用於將元素推入列表的左端(left end)和右端(right end);LPOP 命令和 RPOP 命令分別用於從列表的左端和右端彈出元素;LINDEX 命令用於獲取列表在給定位置上的一個元素;LRANGE 命令用於獲取列表在給定範圍上的所有元素。程式碼清單 1-2 展示了一些列表命令的使用示例,表 1-4 簡單介紹了示例中用到的各個命令。
在這裡插入圖片描述
即使 Redis 的列表只支援以上提到的幾個命令,它也已經可以用來解決很多問題了,但 Redis 並沒
有就此止步—除了上面提到的命令之外,Redis 列表還擁有從列表裡面移除元素的命令、將元素插入
列表中間的命令、將列表修剪至指定長度(相當於從列表的其中一端或者兩端移除元素)的命令,以
及其他一些命令。第 3 章將介紹許多列表命令,但是在此之前,讓我們先來了解一下 Redis 的集合。
1.2.3 Redis 的集合
Redis 的集合和列表都可以儲存多個字串,它們之間的不同在於,列表可以儲存多個相同的字串,而
集合則通過使用散列表來保證自己儲存的每個字串都是各不相同的(這些散列表只有鍵,但沒有與鍵相關聯的值)。本書表示集合的方法和表示列表的方法基本相同,圖 1-3 展示了一個包含 3 個元素的示例集合。
在這裡插入圖片描述

因為 Redis 的集合使用無序(unordered)方式儲存元素,所以使用者不能像使用列表那樣,將元素推入集合
的某一端,或者從集合的某一端彈出元素。不過使用者可以使用 SADD 命令將元素新增到集合,或者使用 SREM命令從集合裡面移除元素。另外還可以通過 SISMEMBER 命令快速地檢查一個元素是否已經存在於集合中,或者使用 SMEMBERS 命令獲取集合包含的所有元素(如果集合包含的元素非常多,那麼 SMEMBERS 命令的執行速度可能會很慢,所以請謹慎地使用這個命令)。程式碼清單 1-3 展示了一些集合命令的使用示例,表 1-5 簡單介紹了程式碼清單裡面用到的各個命令。
在這裡插入圖片描述
在這裡插入圖片描述
跟字串和列表一樣,集合除了基本的新增操作和移除操作之外,還支援很多其他操作,比
如 SINTER、SUNION、SDIFF 這 3 個命令就可以分別執行常見的交集計算、並集計算和差集計
算。第 3 章將對集合的相關命令進行更詳細的介紹,另外第 7 章還會展示如何使用集合來解決多
個問題。不過別心急,因為在 Redis 提供的 5 種資料結構中,還有兩種我們尚未了解,讓我們先
來看看 Redis 的雜湊。
1.2.4 Redis 的雜湊
Redis 的雜湊可以儲存多個鍵值對之間的對映。和字串一樣,雜湊儲存的值既可以是字元
串又可以是數字值,並且使用者同樣可以對雜湊儲存的數字值執行自增操作或者自減操作。圖 1-4
展示了一個包含兩個鍵值對的雜湊。
在這裡插入圖片描述
雜湊在很多方面就像是一個微縮版的 Redis,不少字串命令都有相應的雜湊版本。程式碼清
單 1-4 展示了怎樣對雜湊執行插入元素、獲取元素和移除元素等操作,表 1-6 簡單介紹了程式碼清
單裡面用到的各個命令。
在這裡插入圖片描述
在這裡插入圖片描述
熟悉文件資料庫的讀者可以將 Redis 的雜湊看作是文件資料庫裡面的文件,而熟悉關係資料庫的
讀者則可以將 Redis 的雜湊看作是關係資料庫裡面的行,因為雜湊、文件和行這三者都允許使用者同時訪
問或者修改一個或多個域(field)。最後,讓我們來了解一下 Redis 的 5 種資料結構中的最後一種:有序集合。

1.2.5 Redis 的有序集合
有序集合和雜湊一樣,都用於儲存鍵值對:有序集合的鍵被稱為成員(member),每個成員都是各不相同的;而有序集合的值則被稱為分值(score),分值必須為浮點數。有序集合是 Redis 裡面唯一一個既可以根據成員訪問元素(這一點和雜湊一樣),又可以根據分值以及分值的排列順序來訪問元素的結構。圖 1-5 展示了一個包含兩個元素的有序集合示例。
在這裡插入圖片描述
和 Redis 的其他結構一樣,使用者可以對有序集合執行新增、移除和獲取等操作,程式碼清單 1-5
展示了這些操作的執行示例,表 1-7 簡單介紹了程式碼清單裡面用到的各個命令。
在這裡插入圖片描述
在這裡插入圖片描述
現在讀者應該已經知道有序集合是什麼和它能幹什麼了,到目前為止,我們基本瞭解了 Redis
提供的 5 種結構。接下來的一節將展示如何通過結合雜湊的資料儲存能力和有序集合內建的排
序能力來解決一個常見的問題。

以上知識點解析來自於《Redis實戰》文件其中的一部分!由於不影響觀看,只選取了其中的一部分來展示。
需要完整版的可以