1. Redis簡介
Remote dictionary server
可以用於數據庫、緩存、消息隊列等各種場景
最熱門NoSQL數據庫之一
基於內存數據庫(記憶體效能>IO效能,也就是Redis>MySQL效能)
GitHub、Twitter、Stackoverflow、百度都在使用
2. Redis特點
高性能Key-Value
多種數據結構,單鍵值對最大支持512M大小的數據
豐富的功能
支持數據持久化、主從複製、哨兵模式等高可用分佈特性
2.1. 數據類型
5種基本數據類型
- 字串 String
- 列表 List
- 集合 Set
- 有序集合 SortedSet
- 哈希 Hash
高級數據類型
- 消息隊列 Stream
- 地理空間 Geospatial
- HyperLogLog
- 位圖 Bitmap
- 位域 Bitfield
2.2. 使用方式
主要三種類型
CLI
- redis-cli
API
- 簡單來說就是用程式碼(python、java)的方式進行使用
GUI
- another-redis-desktop-manager
3. 環境安裝
下載docker image
1 | docker pull redis |
container build
1 | docker run --name redis-lab -p 6379:6379 -d redis |
4. Redis GUI 工具
4.1. 這次透過指令方式安裝
1 | choco install another-redis-desktop-manager |
4.2. 執行結果
1 | C:\Windows\System32>choco install another-redis-desktop-manager |
4.3. 確認docker id
1 | C:\Windows\System32>docker ps |
4.4. 進入docker操作redis
1 | C:\Windows\System32>docker exec -it 65b2 bash |
4.5. 透過GUI工具操作
5. String 字串
5.1. 簡介
- Key-Value 存儲: Redis 的 STRING 是一個 key-value 存儲結構,每個 STRING 都有一個唯一的 key 用來標識。
- 二進制安全: Redis 的 STRING 不僅可以存儲文本字符串,還可以存儲任何二進制數據,這使得它非常適合作為緩存系統。
- 操作豐富: Redis 提供了豐富的 STRING 操作命令,包括設置、獲取、刪除、追加等,使得對字符串的操作非常靈活。
5.2. 使用場景
5.2.1. 快取 (Caching)
作為一個支持高性能的快取系統,Redis 的 STRING 可以用來存儲經常被訪問的數據,例如網頁內容、查詢結果,以減輕後端數據庫的壓力。
1 | # 範例:將結果存入 Redis 快取 |
5.2.2. 計數器 (Counters)
可以使用 Redis 的自增(INCR)和自減(DECR)操作,實現計數器的功能,適用於需要跟蹤計數的場景,比如網站訪問次數、商品庫存等。
1 | # 範例:增加訪問次數 |
5.2.3. 會話管理 (Session Management)
存儲和管理用戶的會話數據,比如登錄信息、訪問權限等。
1 | # 範例:存儲用戶會話信息 |
5.3. 常用指令
5.3.1. SET - 設定key
1 | 127.0.0.1:6379> set kite nice |
5.3.2. GET - 讀取key
1 | 127.0.0.1:6379> get kite |
5.3.3. key大小寫有分
1 | 127.0.0.1:6379> set Kite Nice |
5.3.4. DEL - 刪除key
1 | 127.0.0.1:6379> del name |
5.3.5. EXISTS - 查詢key
1 | 127.0.0.1:6379> exists name |
5.3.6. KEYS - 萬用字查詢
1 | 127.0.0.1:6379> keys * |
5.3.7. FLUSHALL - 刪除所有key
1 | 127.0.0.1:6379> flushall |
5.3.8. 中文顯示說明
1 | 127.0.0.1:6379> set name "悠風" |
5.3.9. redis-cli –raw 正常顯示中文方法
1 | 127.0.0.1:6379> quit |
5.3.10. EXPIRE - 設定過期
1 | 127.0.0.1:6379> expire name 10 |
5.3.11. TTL - 查詢過期
1 | 127.0.0.1:6379> ttl name |
5.3.12. SETEX - 設定key + 過期
1 | 127.0.0.1:6379> setex name 5 悠風 |
5.3.13. SETNX - 該值不存在則建立
1 | 127.0.0.1:6379> setnx name kite |
6. LIST 列表
6.1. 簡介
在 Redis 中,LIST 是一種有序、可重複的資料結構,它允許存儲一個有序的元素列表。每個元素都有一個索引,從 0 開始。LIST 提供了豐富的操作命令,可以在列表的頭部或尾部執行插入、刪除等操作,同時支持範圍查詢和修剪。可實現最簡單的先進先出隊列也就是結合LPUSH
(左進) + RPOP
(右出)
LIST 資料結構的特點:
- 有序性: 元素在列表中的存儲順序是有序的,可以按照索引進行訪問。
- 重複元素: 元素可以重複存在於列表中,這使得 LIST 可以用來表示多個相同類型的元素。
- 支持隊列和堆疊操作: LIST 可以被當作隊列(先進先出,FIFO)或堆疊(後進先出,LIFO)來使用。
6.2. 使用場景
6.2.1. 日誌記錄
隊列的特點是先進先出,後進後出.我們可以使用lpush 命令從隊列的左邊放入,然後利用rpop命令從右邊取出,這樣就模擬實現了隊列.可以用來記錄日誌等
6.2.2. 抽獎,搶票
list 是線程安全的,所有的pop操作是原子性的,適用於抽獎,搶票等場景,用來防止超賣問題.這裡重點解釋一下抽獎:主要是分為三步
- 全部獎品打散放入list中
- 呼叫pop指令從list中取出
- 將中獎記錄寫入資料庫
6.2.3. 流量消峰
將所有的請求全部放到list中,然後開啟多個線程來處理後續請求,減輕伺服器壓力,用來處理一些高並發場景.
6.3. 常用指令
6.3.1. LPUSH
第一次
1 | > LPUSH letter a |
第二次
1 | > LPUSH letter b |
第三次
1 | > LPUSH letter c d e |
6.3.2. LRANGE
-1 代表全部
1 | > LRANGE letter 0 -1 |
6.3.3. RPUSH
1 | > RPUSH letter f |
RPOP
1 | > RPOP letter |
LPOP
1 | > LPOP letter 2 |
6.3.4. LLEN
1 | > LLEN letter |
6.3.5. LTRIM
索引從0開始算,所以 1 ~ 3 是 d、c、b
1 | > LPUSH letter a b c d e |
7. SET 集合
7.1. 簡介
SET 與 LIST 最大的差異是沒有順序,並且不能有重複值
7.1.1. 什麼是 Redis SET 資料結構?
在 Redis 中,SET 是一種集合型資料結構,用來存儲多個唯一且無序的元素。SET 不允許相同的元素存在,這意味著每個元素在 SET 中都是唯一的。
7.1.2. Redis SET 的主要特性:
- 唯一性(Unique):SET 中的每個元素都是唯一的,不允許重複的元素存在。
- 無序性(Unordered):SET 中的元素是無序的,不像 LIST 或 ZSET 有順序的概念。
- 操作豐富:Redis 提供了豐富的 SET 操作命令,包括添加成員、刪除成員、檢查成員是否存在等。
7.2. 使用場景
redis set是集合類型的資料結構,那麼集合類型就比較適合用於聚合分類。
7.2.1. 標籤
例如我們部落格網站常常使用到的興趣標籤,把一個個有著相同嗜好,關注類似內容的用戶利用一個標籤把他們進行歸併。
7.2.2. 共同
共同好友功能,共同喜好,或是可以引申到二度好友之類的擴充應用。
7.2.3. 統計
統計網站的獨立IP。利用set集合當中元素不唯一性,可以快速即時統計存取網站的獨立IP。
7.3. 常用指令
7.3.1. SADD
1 | > SADD course Redis |
7.3.2. SMEMBERS
1 | > SMEMBERS course |
7.3.3. SISMEMBER
1 | > SISMEMBER course Redis |
7.3.4. SREM
1 | > SREM course Redis |
7.3.5. 其它學習
SINTER、SUNION、SDIFF
8. SortedSet 有序集合
8.1. 簡介
8.1.1. 什麼是 Redis Sorted Set 資料結構?
在 Redis 中,Sorted Set(有序集合)是一種集合型資料結構,它與 SET 類似,但每個成員都關聯著一個分數(score)。這個分數用來排序集合中的元素,因此 Sorted Set 是根據分數有序排列的。
8.1.2. Redis Sorted Set 的主要特性:
- 有序性(Ordered):元素根據其分數的大小進行排序,可以按照分數區間或排名獲取元素。
- 唯一性(Unique):每個元素在集合中是唯一的,不允許重複的成員存在。
- 操作豐富:Redis 提供了豐富的 Sorted Set 操作命令,包括添加成員、刪除成員、獲取排名、按照分數區間獲取成員等。
8.2. 使用場景
8.2.1. 排行榜(Leaderboard)
Sorted Set 非常適用於實現排行榜,其中成員的分數表示其在排行中的位置,可以根據分數的高低快速獲取排名。
1 | # 範例:將玩家分數存入排行榜 |
8.2.2. 過期時間管理
可以使用 Sorted Set 來管理帶有過期時間的數據,分數表示過期時間的時間戳,並使用定期的清理操作來刪除過期的數據。
1 | # 範例:將帶有過期時間的數據存入有序集合 |
8.2.3. 區間查詢
Sorted Set 支持根據分數區間進行查詢,這使得它適用於需要根據數值範圍檢索數據的場景。
1 | # 範例:獲取分數在指定區間的成員 |
8.2.4. 數據匹配和搜索
Sorted Set 可以用於實現模糊搜索,分數可以表示相似度或匹配程度,使得可以按照相似度檢索數據。
1 | # 範例:根據匹配程度獲取成員 |
8.2.5. 即時排名
Sorted Set 可以用於即時排名的場景,例如遊戲中的實時得分排名。
1 | # 範例:遊戲中即時更新玩家分數 |
8.3. 常用指令
8.3.1. ZADD
1 | 127.0.0.1:6379> ZADD result 100 小民 90 小華 80 小新 |
8.3.2. ZRANGE
只呈現人名
1 | 127.0.0.1:6379> ZRANGE result 0 -1 |
8.3.3. ZRANGE WITHSCORES
分數跟人一起呈現
1 | 127.0.0.1:6379> ZRANGE result 0 -1 WITHSCORES |
8.3.4. ZSCORE
呈現分數
1 | 127.0.0.1:6379> ZSCORE result 小民 |
8.3.5. ZRANK
有序集合預設是由小到大排序,索引從0開始,小民分數最多,所以索引是2
1 | 127.0.0.1:6379> ZRANK result 小民 |
8.3.6. ZREVRANK
rev是指reverse 反轉,也就是由大到小
1 | 127.0.0.1:6379> ZREVRANK result 小民 |
8.3.7. 其它學習
比如刪除某個成員,對某個成員分數進行增加,刪除某個排名範圍的成員
9. Hash 哈希
9.1. 簡介
key-value資料結構,特別適合來儲存物件。
9.2. 使用場景
9.2.1. 對象存儲
Hash 非常適用於存儲對象的屬性,例如用戶對象、產品對象等,其中每個字段表示對象的一個屬性,對應的值是這個屬性的值。
1 | # 範例:存儲用戶對象 |
9.2.2. 網站會話管理
Hash 可以用於存儲網站中的會話信息,其中每個字段表示一個會話屬性,對應的值是這個會話屬性的值。
1 | # 範例:存儲會話信息 |
9.2.3. 配置存儲
Hash 可以用於存儲應用程序的配置信息,其中每個字段表示一個配置項,對應的值是這個配置項的值。
1 | # 範例:存儲應用程序配置 |
9.3. 常用指令
9.3.1. HSET
1 | 127.0.0.1:6379> HSET person name kite |
9.3.2. HGET
1 | 127.0.0.1:6379> HGET person name |
9.3.3. HGETALL
1 | 127.0.0.1:6379> HGETALL person |
9.3.4. HDEL
1 | 127.0.0.1:6379> HDEL person age |
9.3.5. HGETALL
1 | 127.0.0.1:6379> HGETALL person |
9.3.6. HEXISTS
1 | 127.0.0.1:6379> HEXISTS person name |
9.3.7. HKEYS
1 | 127.0.0.1:6379> HKEYS person |
9.3.8. HLEN
1 | 127.0.0.1:6379> HLEN person |
10. 發佈訂閱模式
10.1. 常用指令
10.1.1. subscribe
1 | subscribe ubereats |
10.1.2. publish
1 | publish ubereats order001 |
下圖左邊是publish發佈消息,右邊是兩個訂閱者,當publish時,訂閱者們會同步收到消息。
11. GEO
11.1. 常用指令
11.1.1. GEOADD
經度(116.405285)、緯度(39.904989)、名稱(beijing)
1 | #新增一個 |
11.1.2. GEOPOS
取得地理位置
1 | 127.0.0.1:6379> GEOPOS city beijing |
11.1.3. GEODIST
取得北京到上海的距離,預設單位為公尺(M)
1 | 127.0.0.1:6379> GEODIST city beijing shanghai |
11.1.4. GEOSEARCH…FROMMEMBER…BYRADIUS…
以某某地點為中心,採用半徑方式計算鄰近的城市
1 | 127.0.0.1:6379> GEOSEARCH city FROMMEMBER shanghai BYRADIUS 300 KM |
12. HyperLogLog
12.1. 常用指令
12.1.1. PFADD
建立course課程變數,放三個課程
1 | 127.0.0.1:6379> PFADD course git docker redis |
12.1.2. PFCOUNT
計算課程
1 | 127.0.0.1:6379> PFCOUNT course |
12.1.3. PFMEGER
建立course2課程變數,放三個課程,通過PMERGE
合併課程,再進行計算。
1 | 127.0.0.1:6379> PFADD course2 python git go |
13. Bitmap 位圖
13.1. 常用指令
13.1.1. SETBIT
1 | 127.0.0.1:6379> SETBIT dianzan 0 1 |
13.1.2. GETBIT
1 | 127.0.0.1:6379> GETBIT dianzan 0 |
13.1.3. SET
1 | 127.0.0.1:6379> SET dianzan "\xF0" |
13.1.4. BITCOUNT
1 | 127.0.0.1:6379> BITCOUNT dianzan |
13.1.5. BITPOS
1 | 127.0.0.1:6379> BITPOS dianzan 0 |
14. BitField
14.1. 常用指令
14.1.1. BITFIELD…SET…
player:1
: 變數
u8
: 正整數長度8
#0
:第一個位置
1
:值
1 | #等級1 |
14.1.2. BITFIELD…GET…
1 | 127.0.0.1:6379> BITFIELD player:1 get u8 #0 |
14.1.3. BITFIELD…incrby…
1 | #增加100金幣 |
15. Multi
在執行exec之前,所有命令都會放到佇列中,不會立即執行。
收到exec命令後,有任何一命令失敗,並不影響其它命令。
在執行exec之前,其它客戶提出的請求,並不會被插入到multi裡面。
15.1. 常用指令
15.1.1. MULTI
啟動
15.1.2. EXEC
結束
以下圖為例,當執行了MULTI
之後,接著執行指令SET k1 v1
、SET k2 v2
之後,系統顯示在queued中。
接著,開啟另一個終端機,試著讀取k1
,是沒有資料的,當執行了EXEC
之後,另一個終端機就讀取得到資料。
以下實驗,證明其中一個指令失敗,並不影響其它執令的執行結果:
1 | 127.0.0.1:6379> SET k3 3 |
16. 持久化
16.1. 常用指令
16.2. RDB(Redis Database)
分為自動與手動,自動部分需要去redis.config
檔進行修正,以下是截取部分:
1 | # Unless specified otherwise, by default Redis will save the DB: |
我們可以觀查到,第一個參數表示秒數,第二參數表示執行次數。而docker redis 預設是沒有包redis.config
檔,所以如果要的話請去官網下載,可到下方參考連結去使用,下載檔案之後,在啟動docker時記得mount此份文件,修改其內容。
手動部分實驗如下:
1 | # redis-cli |
可以看到最後兩行有剛剛k1與k2的資料,代表已經實質的從記憶體儲放一份到硬碟上,至於多久要寫入一次的要根據伺服器可用的效能去評估與設定。
補充說明:xxd是一個可以查看2進制或16進制文件內容的linux命令
另外,通常在使用redis時配給的資源通常會給比較多,而在使用save
指令時,redis是無法接受任何請求的,所以有可能會發生阻塞。於是redis又提供了另一個指令bgsave
,這個指令可以直接多開一個執行緒,讓它獨立做記憶體搬到IO的工作。這樣的作法可以讓阻塞問題得到緩解。但是在fork出一個新的執行緒的過程中還是會佔用效能,而且在fork過程式,還是沒有辦法處理任何請求,沒有辦法做到秒級的快照。
為了解決這個問題,又提供了AOF的持久化方式。
16.3. AOF(Append Only File)
AOF
意思是指追加文件,當使用指令時,同時寫入記憶體
與追加文件
,文件以日誌的方式記錄每一個寫入操作,當REDIS重啟動時,就會通過重新執行AOF
文件中的命令來在記憶體中重建整個資料庫的內容。開啟AOF的方式也很簡單,只要在redis.config
將appendonly
後方的no
改為yes
即可。
17. Replication 主從複製
Master(主)節點主要負責寫
的處理,Slave(從)節點負責讀
的處理,主節點的數據變化會通過非同步方式發送給從節點,從節點收到資料後,會更新自己的數據
17.1. Master 建置
這次實驗透過docker進行,準備1個master,2個slave。
docker預設都是吃同一個switch設定,所以自然可以透過區網方式互相訪問。
開始建置master容器,容器取名為redis-master
,指令如下:
1 | docker run --name redis-master -d -p 6379:6379 redis |
我們為了要取得master區網IP,因此需進入容器中,安裝net-tools
工具:
1 | apt-get update |
使用ifconfig
指令,從訊息中得知ip為172.17.0.2
:
1 | # ifconfig |
17.2. Slave 建置
方法1
使用此方法,不需要準備redis.conf
檔
1 | docker run -it --name redis-slave01 -p 6380:6379 redis redis-server --slaveof 172.17.0.2 6379 |
方法2
建置slave容器之前,我們準備一個redis.conf
檔,僅說明需要修改部分(完整檔案放在參考連結那):
1 | replicaof 172.17.0.2 6379 |
使用方法2,開始建置slave容器,容器取名為redis-slave01
,指令如下:
1 | docker run --name redis-slave01 -d -p 6380:6379 -v C:/docker_data/redis-6380.conf:/usr/local/etc/redis/redis-6380.conf redis redis-server /usr/local/etc/redis/redis-6380.conf |
說明相關指令
v C:/docker_data/redis-6380.conf:/usr/local/etc/redis/redis-6380.conf redis
:將準備好的檔案放在c槽,並以volumn 方式放到docker指定位置。
redis-server /usr/local/etc/redis/redis-6380.conf
:redis啟動後參考此config設定
17.3. 實驗階段
17.3.1. 進入Master
容器中,簡單設定幾個變數
1 | # redis-cli |
17.3.2. 進入Slave
容器中,確認同步狀況
1 | docker exec -it 274f /bin/bash |
17.3.3. 再增加一個Slave
,這次特別使用方法1:
1 | docker run -it --name redis-slave02 -p 6381:6379 redis redis-server --slaveof 172.17.0.2 6379 |
節點資源最後如下
17.3.4. Master開始寫入資料,觀查Slave是否同步,如下:
18. 哨兵模式
如果某個節點發生問題,那麼哨兵就會通過發佈訂閱模式來通知其它節點。當主節點不能正常工作時,哨兵會開始一個自動故障轉移的操作,它會將一個從節點升級為新的主節點,然後再將其他從節點指向新的主節點。
18.1. 首先,準備四個docker(1主、2從、1哨)
1 | docker run -it --name redis-master -p 6379:6379 redis redis-server --slaveof 172.17.0.2 6379 |
結果如下:
18.2. 建立sentinel.conf
檔
進入到redis-sentinel
容器中,建立sentinel.conf
檔,檔案內容如下:
1 | sentinel monitor mymaster 172.17.0.2 6379 1 |
參數說明
mymaster
自取名稱,任意填寫172.17.0.2
填master ip6379
master port1
投票人數,這邊只有一個哨兵所以就填1即可。
18.3. 啟動哨兵模式
在redis-sentinel
容器中,執行指令redis-sentinel sentinel.conf
,成功啟動預期如下圖:
18.4. 模擬master中斷
18.5. 觀查哨兵自動轉換
哨兵在自動切換需要一些時間,等待一下…就會看到訊息開始在運作,透過info replication
查看,可以觀查到原本的slave01
升級變為master
,實驗結束,結果如下圖:
19. 模擬排隊程式
1 | // See https://aka.ms/new-console-template for more information |
19.1. 執行過程
19.2. 觀查redis狀況
20. 參考連結
- GUI工具:GitHub:Another Redis Desktop Manager
- 【GeekHour】一小时Redis教程
- 谈谈Redis五种数据结构及真实应用场景
- 分布式锁看这篇就够了
- 有空記得看
- 官網Redis 7.2 config 參考
- 個人筆記-RedisNote
- 包含程式碼範例、redis config檔