BSSZDS930

博客园 首页 新随笔 联系 订阅 管理

主从-哨兵-集群

FROM: https://xuzhongcn.github.io/redis/redis集群搭建.html

集群架构细节:

(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
(2)节点的fail是通过集群中超过半数的节点检测失效时才生效.
(3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任一可用节点即可
(4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

Redis集群的搭建

Redis集群中至少应该有三个节点。要保证集群的高可用,需要每个节点有一个备份机。 Redis集群至少需要6台服务器。 搭建伪分布式。可以使用一台虚拟机运行6个redis实例。然后修改redis的端口号7001-7006(自定义端口,只要不和其他程序重复)

集群模式下,客户端去操作集群是直连到一个具体的节点上操作的。当该节点接收到任何键操作命令时,会先计算键对应的slot,然后根据slot找出对应节点(这里如何找后面会提到),如果对应的节点是自身,则执行键操作命令,返回结果;如果不是自身,会返回给客户端MOVED重定向错误,告诉客户端应该请求具体哪个节点,由客户端发起二次请求到正确的节点,完成本次键操作。

管道

  • 非pipeline:client请求,redis server响应,期间client阻塞
  • Pipeline:允许client将多个请求依次发给服务器,过程中而不需要等待请求的回复,在最后再一并读取结果即可。
# Redis实例创建及管道 pip install redis-py-cluster==1.3.6
# Note: 与python3一起使用时,decode_responses必须设置为True
# max_connections最大连接数,如果设20,那么在建立20个连接时会报错。
  
import redis, rediscluster
from rediscluster.connection import ClusterConnectionPool
from zlib import compress, decompress
	
# 主从模式	
pool = redis.ConnectionPool(host=xxx, port=xxx, socket_timeout=xx, db=x, password=x, decode_responses=False)   # 多个redis实例共享一个连接池。
r = redis.StrictRedis(connection_pool=pool, decode_responses=False)   # redis.Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py
{
    # 管道
    pipe = r.pipeline(transaction=True)     # 主从。默认执行每次请求都会创建(pool申请连接)和断开(归还pool)操作。用pipline实现一次请求指定多个命令.
    pipe = redis.pipeline()   # 集群
    pipe.set('key', 'value')
    pipe.execute()   # 批量,数量限制?
}

	
# redis集群模式
rc = rediscluster_xx.RedisCluster(cluster=XX, db=XX, fail_count_to_reload=xx, fail_time_to_reload=xx)  # ???
rc = rediscluster.RedisCluster(startup_nodes=[{"host": "xx", "port": xx}], skip_full_coverage_check=True, socket_timeout=timeout, socket_connect_timeout=timeout)
rc = rediscluster.RedisCluster(host='xx', port=xx, socket_timeout=5, skip_full_coverage_check=True)
{
    # 连接池
    from rediscluster.connection import *
    pool = ClusterConnectionPool(startup_nodes=[{"host": "xx", "port": xx}], password="*", socket_timeout=5, db=0, decode_responses=False, skip_full_coverage_check=True)   # connection_class=SSLClusterConnection
    r =rediscluster.RedisCluster(connection_pool=pool)
}	


# test
redis = redis.Redis(host='127.0.0.1', port=5392, password="", db=7)
data = json.loads(decompress(redis.hget('book', 690)).decode())
# redis.hget("book", 154)
# redis.hdel("book", 711)
redis.hset('book', 711, compress(json.dumps(data, ensure_ascii=False).encode()))
  • SELECT is not allowed in cluster mode 集群模式不用默认db=0
  • redis.exceptions.ResponseError: MOVED 7074 ip:port 启动redis-cli时没有设置集群模式所导致
  • rediscluster.exceptions.RedisClusterException: ERROR sending 'config get cluster-require-full-coverage' command to redis server: 设置skip_full_coverage_check=True
  • error: transaction is deprecated in cluster mode. cause: pipe = rc.pipeline() 管道在集群模式与正常模式下不同。创建此对象的副本,以便模拟管道正常工作。每个命令将在使用时直接调用,并且在调用execute()时仅返回结果堆栈。
posted on 2020-06-02 19:57  BSSZDS930  阅读(722)  评论(0编辑  收藏  举报