Python 同步和異步使用Redis集羣的方法

目前在做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

下載docker鏡像

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

啓動redis單機版

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

同步連接redis單機

導入 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

異步連接redis單機

異步編程用官方模塊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

docker 部署 redis cluster 集羣

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
  1. 創建集羣
    登錄到其中一個redis,執行集羣創建命令
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集羣

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 cluster集羣

redis.asyncio.cluster中導入ClusterNodeRedisCluster,注意不能用同步模塊的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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章