本章主要內容
Redis 與其他軟件的相同之處和不同之處
Redis 的用法
使用 Python 示例代碼與 Redis 進行簡單的互動
使用 Redis 解決實際問題
以下知識點解析來自於《Redis實戰》文檔其中的一部分!由於不影響觀看,只選取了其中的一部分來展示。
需要完整版的可以點擊這里!!暗號CSDN,獲取!
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實戰》文檔其中的一部分!由於不影響觀看,只選取了其中的一部分來展示。
需要完整版的可以點擊這里!!暗號CSDN,找群主獲取!