目前在做Python專案用到同步和非同步的方法使用Redis單機,現在要增加相容Redis叢集。也就說當前專案用到中以下4種Python使用Redis的方法都用到了。
- | 同步 | 非同步 |
---|---|---|
單機 | 涉及 | 涉及 |
叢集 | 涉及 | 涉及 |
並且由於Redis單機版用的是redis-py
這個官方模組,所以叢集也需要使用同樣的模組。
早期的redis-py
不支援叢集的連線,網上能查到叢集的連線是用另一個模組redis-py-cluster
。其實redis-py
後面整合了redis-py-cluster
叢集相關的連線,所以也能支援叢集連線。
可以參見包的介紹:https://pypi.org/project/redis/
本文介紹以上4種連線方法。
本地環境
:
Python:3.8
Redis:4.3.4
redis到目前已經更新到redis7.0.2,本文使用redis5.0.4,同時使用較為簡單的docker來部署。首先下載docker映象 redis 5.0.4
docker pull redis:5.0.4
docker pull redis:5.0.4
5.0.4: Pulling from library/redis
29b80961214d: Pull complete
4c417db3b6fe: Pull complete
262a0c65662c: Pull complete
36db11a6661e: Pull complete
d5d8b9326480: Pull complete
4e9148e44a67: Pull complete
Digest: sha256:2dfa6432744659268d001d16c39f7be52ee73ef7e1001ff80643f0f7bdee117e
Status: Downloaded newer image for redis:5.0.4
docker.io/library/redis:5.0.4
ljk@192 ~ % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis 5.0.4 b61ab367aee1 3 years ago 90MB
docker run -itd --name=redis0 redis:5.0.4
(ymir) ➜ docker run -itd --name=redis0 redis:5.0.4
75ec79bd233c917fb681e224559c67a5e90c55089ffd01b1df8d939795b70746
(ymir) ➜ nacos git:(dev) docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4e7ab577003c redis:5.0.4 "docker-entrypoint.s…" 53 seconds ago Up 52 seconds 6379/tcp redis0
檢視docker的ip地址
docker inspect redis0
可以得到redis0的ip地址是 172.17.0.8
匯入 StrictRedis
模組,連線redis。這裡留意一下:
Redis 提供兩個類 Redis 和 StrictRedis, StrictRedis 用於實現大部分官方的命令,Redis 是 StrictRedis 的子類,用於向後兼用舊版本。所以優先使用StrictRedis。
import asyncio
def sync_singal():
from redis import StrictRedis
ip = "172.17.0.8"
redis_conn = StrictRedis(
host=ip,
port=6379,
encoding="utf8",
decode_responses=True,
db=0,
)
redis_conn.set("name", "sync singal")
res = redis_conn.get("name")
print(res)
sync_singal()
結果:
(ymir) ➜ Desktop python redis_learn.py
sync singal
非同步程式設計用官方模組asyncio
實現,注意匯入的庫是redis.asyncio
。需要在連線、設定、獲取等使用redis的地方可等待。
import asyncio
async def async_singal():
from redis.asyncio import StrictRedis
ip = "172.17.0.8"
redis_conn = await StrictRedis(
host=ip,
port=6379,
encoding="utf8",
decode_responses=True,
db=0,
)
await redis_conn.set("name", "async singal")
res = await redis_conn.get("name")
print(res)
asyncio.run(async_singal())
結果:
(ymir) ➜ Desktop python redis_learn.py
async singal
redis的叢集有三種,這裡以cluster叢集為例,使用docker快速搭建一個cluster叢集。
cluster叢集要求至少三個節點組建成3個master節點,下面使用6個節點,組成三主三從經典叢集。
1.啟動docker
docker run -itd --name redis-nodes1 redis:5.0.4 --cluster-enabled yes
docker run -itd --name redis-nodes2 redis:5.0.4 --cluster-enabled yes
docker run -itd --name redis-nodes3 redis:5.0.4 --cluster-enabled yes
docker run -itd --name redis-nodes4 redis:5.0.4 --cluster-enabled yes
docker run -itd --name redis-nodes5 redis:5.0.4 --cluster-enabled yes
docker run -itd --name redis-nodes6 redis:5.0.4 --cluster-enabled yes
2.查詢所有docker的ip
查詢出所有docker的ip,用於組建叢集
docker inspect redis-nodes1
得到所有節點的ip
節點 | IP地址 |
---|---|
redis-nodes1 | 172.17.0.2 |
redis-nodes2 | 172.17.0.3 |
redis-nodes3 | 172.17.0.4 |
redis-nodes4 | 172.17.0.5 |
redis-nodes5 | 172.17.0.6 |
redis-nodes6 | 172.17.0.7 |
redis-cli --cluster create 172.17.0.2:6379 172.17.0.3:6379 172.17.0.4:6379 172.17.0.5:6379 172.17.0.6:6379 172.17.0.7:6379 --cluster-replicas 1
--cluster-replicas 1 表示主從節點比例是1:1。如果是0則表示沒有從節點
4.檢查叢集是否建立成功
進入redis使用者端,執行命令cluster nodes
如上就表示cluster叢集建立成功
從redis.cluster
匯入RedisCluster
,將所有節點資訊打包成一個列表
import asyncio
def sync_cluster():
from redis.cluster import ClusterNode
from redis.cluster import RedisCluster
cluster_nodes = [
ClusterNode("172.17.0.2", 6379),
ClusterNode("172.17.0.3", 6379),
ClusterNode("172.17.0.4", 6379),
ClusterNode("172.17.0.5", 6379),
ClusterNode("172.17.0.6", 6379),
ClusterNode("172.17.0.7", 6379),
]
redis_conn = RedisCluster(
startup_nodes=cluster_nodes,
password=None,
encoding="utf8",
decode_responses=True,
)
redis_conn.set("name", "sync cluster")
res = redis_conn.get("name")
print(res)
sync_cluster()
(ymir) ➜ Desktop python redis_learn.py
async singal
從redis.asyncio.cluster
中匯入ClusterNode
和RedisCluster
,注意不能用同步模組的ClusterNode,兩者名稱一致但是方法不同。
async def async_cluster():
from redis.asyncio.cluster import ClusterNode
from redis.asyncio.cluster import RedisCluster
cluster_nodes = [
ClusterNode("172.17.0.2", 6379),
ClusterNode("172.17.0.3", 6379),
ClusterNode("172.17.0.4", 6379),
ClusterNode("172.17.0.5", 6379),
ClusterNode("172.17.0.6", 6379),
ClusterNode("172.17.0.7", 6379),
]
redis_conn = await RedisCluster(
startup_nodes=cluster_nodes,
password=None,
encoding="utf8",
decode_responses=True,
)
await redis_conn.set("name", "async cluster")
res = await redis_conn.get("name")
print(res)
asyncio.run(async_cluster())
結果:
(ymir) ➜ Desktop python redis_learn.py
async cluster
非同步叢集需要注意的是,如果叢集有密碼,需要在ClusterNode
中設定密碼,如下:
cluster_nodes = [
ClusterNode("172.17.0.2", 6379, password="xxx"),
ClusterNode("172.17.0.3", 6379, password="xxx"),
ClusterNode("172.17.0.4", 6379, password="xxx"),
ClusterNode("172.17.0.5", 6379, password="xxx"),
ClusterNode("172.17.0.6", 6379, password="xxx"),
ClusterNode("172.17.0.7", 6379, password="xxx"),
]
看起來比較奇怪,從redis-py的原始碼和實際使用中看確實如此。
參考:
https://blog.csdn.net/zyooooxie/article/details/123760358