3

Python 同步和异步使用Redis集群的方法 - 金色旭光

 1 year ago
source link: https://www.cnblogs.com/goldsunshine/p/17083787.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

1060878-20230202091638435-1590448102.png

目前在做Python项目用到同步和异步的方法使用Redis单机,现在要增加兼容Redis集群。也就说当前项目用到中以下4种Python使用Redis的方法都用到了。

- 同步 异步
单机 涉及 涉及
集群 涉及 涉及

并且由于Redis单机版用的是redis-py这个官方模块,所以集群也需要使用同样的模块。

1060878-20230201180547408-578306637.png

早期的redis-py不支持集群的连接,网上能查到集群的连接是用另一个模块redis-py-cluster。其实redis-py后面整合了redis-py-cluster集群相关的连接,所以也能支持集群连接。

可以参见包的介绍:https://pypi.org/project/redis/

1060878-20230201180612082-2033890692.png

本文介绍以上4种连接方法。
本地环境
Python:3.8
Redis:4.3.4

1|0下载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

2|0启动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

1060878-20230201180646269-1633514705.png

可以得到redis0的ip地址是 172.17.0.8

3|0同步连接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

4|0异步连接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

5|0docker 部署 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

1060878-20230201180730384-810483026.png

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则表示没有从节点

1060878-20230201180744279-1135052977.png

4.检查集群是否创建成功

进入redis客户端,执行命令cluster nodes

1060878-20230201180800678-1011230123.png

如上就表示cluster集群创建成功

6|0同步连接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

7|0异步连接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

__EOF__


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK