目錄
第一部分 Redis 安裝
一、Windows 上安裝 Redis
由於 Redis 沒有官方的 Windows 版本,所以需要在 Windows 上安裝第三方的 Windows 版本的 Redis,但該第三方的 Redis 版本太低,只適合測試用,無法用在正式的生產環境中,因此一般還是推薦在 Linux 上安裝 Redis。
-
下載第三方 Redis 版本:https://github.com/MicrosoftArchive/redis/releases/。
下載這兩個都可以,msi 是可執行的文件格式,這裏下載 zip 格式的。 -
解壓之後,將 Redis 目錄配置到環境變量,打開 cmd,執行下列命令啓動 Redis 服務:
redis-server
執行命令後會出現如下界面:
這時候,Windows 防火牆會彈出報警窗口,勾選“專用網絡”,並點擊“允許訪問”:
-
再打開一個 cmd(之前的不要關),輸入如下命令進入 Redis 交互環境:
redis-cli
進入交互環境,輸入幾條命令試試有沒有安裝成功:
二、Ubuntu 上安裝 Redis
相較於在 Windows 上安裝 Redis,在 Ubuntu 系統上打開 Terminal 終端通過下面的命令就可以安裝,很方便:
apt-get update
apt-get install redis-server
和剛纔 Windows 上一樣的,先啓動 Redis 服務,然後再打開一個終端進入交互環境:
redis-server
redis-cli
三、Mac OS 上安裝 Redis
打開終端,從源碼編譯安裝,依次輸入下列命令:
cd 準備好的安裝目錄
wget http://download.redis.io/releases/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make
sudo ln -s 安裝目錄/redis-stable/src/redis-server /bin/redis-server
sudo ln -s 安裝目錄/redis-stable/src/redis-cli /bin/redis-cli
redis-server 安裝目錄/redis-stable/src/redis.conf
四、安裝 redis-py 第三方庫
redis-py 是 Redis 在Python 上的第三方庫,可以通過以下方式安裝:
python3 -m pip install redis
或
pip3 install redis
打開 Python 交互環境,嘗試導入 redis,如果系統不報錯,則說明導入成功,即安裝成功:
第二部分 初步瞭解 Redis
一、基本準備
-
Redis 可以存儲鍵 Key 與 5 種不同的基本數據結構類型之間的映射,這 5 種數據結構類型分別爲 STRING(字符串)、LIST(列表)SET(集合)、HASH(散列)和 ZSET(有序集合)。
-
鍵 Key 可以是數字、大小寫字母、下畫線或者中文,但不建議使用中文。
-
Redis 的命令是不區分大小寫的,一般小寫方便於辨認,不過需要注意的是,Redis 中的鍵和值的書寫是區分大小寫的。
-
Redis 有一個在線測試的網站,可以在上面進行一系列 Redis 的數據庫操作,和安裝在本機上的 Redis 有着同樣的效果,網址:http://try.redis.io/。
-
通過下列命令可以查看當前數據庫中所有的 Key:
keys *
注意,如果 Redis 中有大量 key,那麼執行
keys *
命令會對 Redis 性能造成短暫影響,甚至導致 Redis 失去響應。因此,絕對不應該在不清楚當前有多少 key 的情況下冒然列出當前所有的 key。 -
雖然 key 可以使用中文,但是使用 redis-cli 打開交互界面時不建議使用,因爲在列出當前所有 key 時,中文內容會顯示亂碼,變得難以閱讀,不過使用 redis-cli --raw 打開交互界面可以解決中文問題:
注意,在 Windows 上安裝第三方 Redis 的可能會出現奇怪的情況,也是亂碼,但亂得離譜,如下:
網上說是 cmd 編碼默認爲 gbk 的原因,然後我在 cmd 上執行 chcp 65001 命令(修改爲 utf-8 編碼)之後再進 redis,結果一輸中文就會閃退(不過確實可以顯示那麼一兩秒),我懷疑是版本太低的原因,因爲 Windows 上安裝的第三方的 Redis 版本才更到 3.2 的版本,之後去 Linux 系統上安裝了一個新版本的 Redis,輸中文沒有問題,如果沒有 Linux 系統的朋友建議在 Windows 上安裝 Docker,然後在 Docker 上弄。 -
redis-py 操作數據庫使用的關鍵字與 redis-cli 基本一致,只是形式不一樣,下面展示一下使用 redis-py 的示例:
首先,在做數據庫操作之前,肯定都要連接 Redis 數據庫,如下:
import redis # 創建一個 Redis 的客戶鏈接 client = redis.Redis()
然後我們嘗試一下如何實現剛剛說過的基本操作
keys *
:# 等價於 redis-cli 下的 keys *,中文顯示會亂碼,因爲它返回的是 bytes 型的 key 的列表 keys = client.keys() print(keys) # 等價於 redis-cli --raw 下的 keys *,可以顯示中文 keys = [key.decode() for key in keys] print(keys)
該段代碼和 redis-cli 中的命令
kesy *
的效果類似,會打印數據庫中所有的 Key,類似如下輸出:
二、字符串
Redis 中的字符串相對而言比較好理解,下面依次展示一下它的基本操作。
1 創建字符串
在 Redis 中,創建字符串的基本形式爲 set key value
,例如:
set hello i_am_chinese
如果值的內容有空格,那麼直接添加值就會報錯,爲防止報錯,則需要使用雙引號把有空格的內容包起來,格式如下:
set "Hello" "I am Chinese"
在 key 當中使用冒號是表示作爲分隔符,沒有特殊意義,使用其他分隔符亦可:
set Chinese:Wuhan "Beautiful!"
使用 redis-py 創建字符串的方式如下,打印出 True
說明創建成功:
print(client.set("武漢", "陷入困境"))
2 獲取字符串
在 Redis 中,創建字符串的基本形式爲 get key
,例如:
get Chinese:Wuhan
如果試圖獲取一個不存在的 Key,則會返回 (nil)。
使用 redis-py 獲取字符串的方式如下,打印出 陷入困境
說明獲取成功:
value = client.get("武漢")
print(value.decode())
如果要獲取現在數據庫中的全部字符串,可以使用如下方法(此時數據庫應沒有其他數據結構,否則該段代碼執行會出錯):
values = [client.get(key).decode() for key in keys]
print(values)
3 更新字符串
通過 set 命令就可以更新字符串,非常方便,基本格式爲 set key new_value
,例如:
set Hello "你才日本人呢!I'm Chinese!"
不過如果不希望 set 命令覆蓋舊值的話,可以使用參數“NX”,使用該參數時,如果 key 已經存在與 Redis 中,那麼就不覆蓋,直接放棄放棄操作:
set Hello "我是火星人" NX
如果需要做的更新是給字符串末尾加上其他字符串,則可以不使用 set 命令,而改用 append 命令,基本格式爲 append key append_value
:
append Hello "我也不是火星人"
使用 redis-py 更新字符串的方式如下
print(client.set("武漢", "加油"))
print(client.get("武漢").decode())
print(client.set("武漢", "暫停", nx=True))
print(client.get("武漢").decode())
print(client.append("武漢", "必勝"))
print(client.get("武漢").decode())
出現如下結果,說明操作成功,第三行的 None
是因爲我們將 nx 參數設置爲了 True
,而 武漢
已經存在與 Redis 中,那麼就不覆蓋,直接放棄更新操作,返回 None
:
4 數字操作
字符串作爲一個數據結構,雖然命名爲字符串,但也可以保存數字,基本格式也是 set key value
,例如:
set year 2020
我們還可以通過以下命令來改變數字的值:
數字加一:incr year
數字減一:decr year
數字增加 n:incrby year 5
數字減少 n:decrby year 3
在 redis-py 中,client.incr() 與 client.decr() 都可以接收兩個參數,第 1 個參數是 key,第 2 個參數是數字,第 2 個參數可以省略,省略時表示 1,如下:
print(client.set("students_num", 60))
print(client.incr("students_num", 1))
print(client.decr("students_num", 1))
print(client.incr("students_num", 10))
print(client.decr("students_num", 4))
執行代碼會輸出如下結果,client.incr() 與 client.decr() 都會返回操作後數字的值:
4 注意事項
-
使用 redis-py 時,不論是 Python 的字符串還是數字,一旦進了 Redis 再出來就會變成 bytes 型的數據,因此需要注意做好格式轉換,如下:
print(client.set("students_num", 60)) number = client.get("students_num") print(number) print(type(number))
執行代碼會出現下面的輸出:
-
在工程上,Redis 的字符串常用來記錄簡單的映射關係,比如記錄用戶的 ID 和用戶名,一般只應用在小量級的數據記錄中。如果數據量超過百萬級別,那麼使用字符串來保存簡單的映射關係將會浪費大量內存。此時需要使用 Redis 的另一種數據結構 Hash,儲存相同量級的數據,Hash 結構消耗的內存只有字符串結構的 1/4, 但查詢速度卻不會比字符串差。
-
由於 Redis 的數據保存在內存中,所以查詢的速度非常快,可以滿足對查詢速度要求比較高但查詢邏輯簡單的查詢操作。
三、列表
Redis 中的列表,與 Python 的列表在行爲上有不少相似之處,可以對比着學習,Redis 的列表有 17 條不同的操作命令,下面通過操作展示 7 條常用命令。
1 插入數據
Redis 的列表插入數據的基本格式爲 lpush key value1 value2 value3
和 rpush key value1 value2 value3
,我們可以插入 1 個或者多個數據,如果有多個,應使用空格將它們隔開,如果一個數據內部本身就有空格,那麼就使用引號包起來,例如:
從列表左側插入數據
lpush database mysql mongodb redis
從列表右側插入數據
rpush example Hi "Are you OK"
需要注意的是,執行插入命令時,寫在左邊的數據先插入,redis 的列表真的很像一個雙端的棧,如下所示,其中,插入數據時返回的數字表示加上插入的數據後列表中的元素個數:
使用 redis-py 實現:
print(client.lpush("num", 11, 22))
print(client.rpush("num", 33, 44))
插入多個數據比較方便的是通過以下操作實現,在 Python 的列表的左側使用星號表示將列表解開成多個獨立的實參傳入函數:
datas = [1, 2, 3, 4]
print(client.lpush("num", *datas))
datas = [5, 6, 7, 8]
print(client.rpush("num", *datas))
以上這些插入數據的代碼執行的輸出爲:
2 查看列表的長度
查看列表長度的基本格式爲 llen key
,例如:
llen num
使用 redis-py 實現:
print(client.llen("num"))
3 根據索引查看列表數據
Redis 的列表也有索引,從 0 開始編號,基本格式爲 lrange key 開始索引 結束索引
,如果結束索引超出索引範圍,會返回列表所有數據,例如:
lrange num 0 100
使用 redis-py 實現:
print(client.lrange("num", 0, 100))
將返回的元素轉化成非 bytes 型:
print([element.decode() for element in client.lrange("num", 0, 100)])
4 彈出並刪除數據
Redis 中的列表可以分別從左邊和右邊彈出數據然後將該數據返回,並且會在列表中刪除彈出的數據,基本格式爲 lpop key
和 rpop key
,例如:
lpop num
rpop num
使用 redis-py 實現:
print(client.lpop("num"))
print(client.rpop("num"))
5 修改數據
Redis 列表修改其中的數據也很簡單,基本格式爲 lset key index new_value
,例如:
lset num -1 32
使用 redis-py 實現:
print(client.lset("num", 0, 0))
6 注意事項
-
列表裏可以有成千上萬上百萬的數據,所以,使用列表控制 Key 的規模是一種比較好的選擇。
-
Redis 的列表雖然和 Python 中的列表相似,但是還有一些差別,比如說索引“切片”操作,python 列表切片時不包含冒號右邊的索引對應的值,但 redis 列表包含,如下:
-
由於一個列表可以儲存幾百萬條數據,所以,絕對不可冒然列出一個列表裏面的所有數據,否則可能導致大量數據輸出而瞬間耗盡系統的 I/O 資源,我們應該先查看列表的長度,如果確定數據量很小,則列出所有的值;如果數據量很大,則可以使用索引查看頭幾條數據與末尾幾條數據。
四、集合
在工程中,Redis 的集合一般有兩種用途,一種是根據集合內數據不重複的特性實現去重並記錄信息,另一種是利用多個集合計算交集、並集和差集。
Redis 的集合與 Python 的集合有非常多的相似之處,可以對比學習,集合有 15 條操作命令,下面介紹一下常用的 9 條命令。
1 插入數據:
與 Redis 列表不同,Redis 集合插入數據時返回的值表示實際插入數據的數量,如果要插入的元素已經在集合中,則返回 0,插入數據的基本格式爲 sadd key value1 value2 value3
,例如:
sadd students "張三" "李四" "王五" "Tony" "Smith" "Alice"
使用 redis-py 實現:
print(client.sadd("students", "張三", "Tom", "王五", "二蛋", "小明", "大黃", "黑子"))
這句 Python 代碼會打印出 5 而不是 7,因爲 “張三” 和 “王五” 這兩個值已經在 students 集合當中了,因此此時實際插入的數據只有其他 5 個,因此返回值是 5。
2 查看集合中元素數量:
查看集合中有多少個元素可以使用 scard
命令來完成,基本格式爲 scard key
,例如:
scrad students
使用 redis-py 實現:
print(client.scard("students"))
3 隨機獲取集合中的數據:
可以使用 spop
命令來隨機獲取集合中的數據,獲取的同時,該數據也從集合中刪除,該操作和 Redis 列表的彈出操作類似,只不過沒有方向之說了,而是隨機的,其基本格式爲 spop key [count]
,count 可選,默認爲 1,如果 count 超過集合中元素的總數量,則獲取集合中所有元素,例如:
spop students 2
使用 redis -py 實現:
print(client.spop("students"))
注意,Python 中,spop 無 count 參數,一次只能獲取一條數據,因此想要獲取集合當中所有,可以使用循環實現:
for i in range(3):
print(client.spop("students"))
4 獲取集合中所有數據:
使用 smembers 命令獲取集合中所有數據不會刪除數據,基本格式爲 smembers key
,例如:
smembers students
也可以通過 redis-py 實現,不過函數返回的數據格式爲 Python 中的集合,注意,返回的集合中的元素都是 bytes 類型的:
print(client.smembers("students"))
要警惕的是,如果集合裏的數據量極大,就應該慎重使用獲取所有數據,因爲這樣會導致系統的 I/O 資源瞬間被耗盡。
5 判斷集合是否包含某個元素:
有時候,我們想判斷某個元素是否在集合當中來幫助我們進行決策,基本格式爲 sismember key value
,例如:
sismember students "黑子"
使用 redis-py 實現:
print(client.sismember("students", "二蛋"))
6 刪除數據:
刪除數據命令的基本格式爲 srem key value1 value2 value3
,如果刪除不存在的數據,並不會報錯,只會返回實際刪除的元素的個數,例如:
srem students "米老鼠" "Tom" "二蛋"
使用 redis-py 實現:
print(client.srem("students", "混蛋", "Tony"))
7 集合的交、並、差
集合的交、並、差通常可以很方便地幫助我們處理集合,下面是它們分別在 redis-cli 和 redis-py 上的基本格式,至於例子就不舉了,這些都是大家非常熟悉的東西了:
-
集合的交:
sinter key1 key2 key3
client.sinter(key1, key2, key3)
-
集合的並:
sunion key1 key2 key3
client.sunion(key1, key2, key3)
-
集合的差,求所有隻在 key1 集合中有,而 key2、key3 集合中沒有的數據構成的集合
sdiff key1 key2 key3
client.sdiff(key1, key2, key3)