zoukankan      html  css  js  c++  java
  • Redis之集群

    一:简介

    一:特点

    Redis集群是一个可以在多个Redis节点之间进行数据共享的设施

    Redis集群不支持那些需要同时处理多个键的Redis命令,因为执行这些命令需要在多个Redis节点之间移动数据,并且在高负载的情况下,会降低Redis集群的性能

    Redis集群通过分区来提供一定程度的可用性,即使集群中有一部分节点失效或者无法继续通讯,集群也能继续处理命令请求,同时将数据切分到多个节点的能力

    二:集群数据共享

    一:定义

    redis集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现,一个redis集群包含16384个哈希槽(hash slot),数据库中的每个键都属于这16384中的一个,其使用集群公式CRC16(key)%16384来计算key属于哪个槽位,其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。

    节点 A 负责处理 0 号至 5500 号哈希槽。
    
    节点 B 负责处理 5501 号至 11000 号哈希槽。
    
    节点 C 负责处理 11001 号至 16384 号哈希槽。

    二:槽的计算公式

    集群使用公式 CRC16(key) & 16383 计算键 key属于哪个槽。

     

    三:集群运行机制

    所有redis节点彼此互连(ping-pong机制),内部使用二进制协议优化传输速度和带宽

    节点的fail是通过集群中超过半数的master节点检测失效时候才失效

    客户端与节点之间相连,连接集群中任何一个可用的节点即可

    把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->key

     在redis集群中为了使得一部分节点在下线或者无法与集群大多数(majority)节点进行通讯的情况下,仍然可以正常运作,redis集群对节点使用主从复制功能,集群中的每个节点都有1至N个复制品,其中一个复制品为主节点(master),其余N-1为从节点(slave)

    假设在上图中A B C三个节点中 因为某些原因A节点下线 那么redis集群将不能正常工作 因为集群找不到节点来处理0-5000的哈希槽
    
    假如我们在创建集群之前(或者在A节点下线之前)创建了A的从节点A1 那么当A节点下线的时候 A1这个从节点会成为新的主节点 继续处理0-5000的哈希槽位 此时集群不会因为A节点的下线 导致集群无法正常使用
    
    # 如果A1这个从节点此时也下线 那么集群仍然会失败

    集群的复制特性重用了 SLAVEOF 命令的代码,所以集群节点的复制行为和SLAVEOF 命令的复制行为完全相同。

    四:集群故障迁移

    一:转移原理

    在redis集群中,节点与节点之间会进行检查

    当一个主节点下线的时候,其余主节点会检测下线的节点,并进行故障转移

    换句话说,集群节点继承了线下检测以及故障转移等功能 有点类似于Sentinel的功能

    因为Sentinel是一个独立的监控程序 而集群之间的下线检测以及故障转移是在节点内部完成的,其虽然功能很相似,但是运行模式并不相同,集群并没有实现Sentinel的代码

    二:集群命令转发

    情况一:发送到正确的节点

    命令所处理的键所在的槽位正好在该节点的槽内,那么该节点就会想单机redis一样执行该命令

     情况二:发送到错误的节点

    接收到命令的的节点并非处理键所在槽的节点,其会发送一个转向错误(redirection),告知客户端去那个节点处理该命令,客户端会根据错误提示信息,重新向正确的节点发送命令信息

     客户端根据转向错误 向正确的那个节点发送指令

     五:转向错误

    在集群中每个节点都会告诉其余节点自己所维护的槽

     集群中每个节点都会记录0-16384这些槽位有哪些节点负责,所有节点将槽汇聚在一起,从而形成一个槽表(slot table)

    节点在收到键的时候 会通过槽表查看该键位所在的槽是否在自己当前的槽范围内

    1:如果在 该节点则会执行该命令

    2:如果不在 则会从槽表取出正确的节点地址信息 然后发送转向错误 告诉客户端

    给定 redis-trib.rb 程序的命令是 create , 这表示我们希望创建一个新的集群。

    选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。

    七:集群管理

    redis集群搭建

    Redis下载安装

    下载

    wget http://download.redis.io/releases/redis-3.2.4.tar.gz

    安装

    yum -y install gcc gcc-c++ kernel-devel # 下载依赖
    tar -zxvf redis-3.2.4.tar.gz -C /usr/loacl
    cd redis-3.2.4
    make
    make PREFIX=/usr/local/redis install

    环境变量

    vim /etc/profile
    export PATH="$PATH:/usr/local/redis/bin"
    # 保存退出

    # 让环境变量立即生效
    source /etc/profile

    集群搭建

    拷贝文件

    cd /usr/local/redis-3.2.4/src/
    cp redis-trib.rb /usr/local/bin/

    创建集群文件

    mkdir /usr/local/redis-cluster/ 
    cd /usr/local/redis-cluster/
    mkdir {7000,7001,7002,7003,7004,7005}
    cp redis-3.2.4/redis.conf redis-cluster/7000 # 依次复制到上述的文件夹

    修改配置文件

    # 其余配置文件下同
    cd /usr/local/redis-cluster/7000
    vim redis.conf
       84 port 7000 #端口[7000-7005]
       61 bind 0.0.0.0 #IP根据节点机器可访问IP
       128 daemonize yes #redis后台运行
       150 pidfile /var/run/redis_7000.pid #pidfile文件对应[7000-7005]
       247 dir /usr/local/redis-cluster/7000 #目录端口必须配置指定,否则无法启动
       593 appendonly yes #打开持久化

       721 cluster-enabled yes  #开启集群模式
       729 cluster-config-file nodes-7000.conf #集群的配置,配置文件首次启动自动生成
       735 cluster-node-timeout 6000 #请求超时自行设置

    redis-server 7000/redis.conf # 启动redis 其余的配置文件依旧

    ruby

    安装

    yum -y install ruby rubygems && gem install redis -v 3.2.2

    创建redis集群

    redis-trib.rb create --replicas 1 0.0.0.0:7000 0.0.0.0:7001 0.0.0.0:7002 0.0.0.0:7003 0.0.0.0:7004 0.0.0.0:7005 # 开启集群

    启动集群

    redis-cli -c -h 127.0.0.1 -p 7002

    CLUSTER INFO # 查看集群信息

    CLUSTER NODES # 查看集群节点

    创建开机自启脚本

    vim /etc/init.d/redis
    
    
    #!/bin/sh
    # chkconfig: 2345 80 90
    #
    # Simple Redis init.d script conceived to work on Linux systems
    # as it does use of the /proc filesystem.
    REDISPORT1=7000
    REDISPORT2=7001
    REDISPORT3=7002
    REDISPORT4=7003
    REDISPORT5=7004
    REDISPORT6=7005
    EXEC=/usr/local/redis/bin/redis-server
    CLIEXEC=/usr/local/redis/bin/redis-cli
    PIDFILE=/var/run/redis_${REDISPORT1}.pid
    CONF1="/usr/local/redis-cluster/${REDISPORT1}/redis.conf"
    CONF2="/usr/local/redis-cluster/${REDISPORT2}/redis.conf"
    CONF3="/usr/local/redis-cluster/${REDISPORT3}/redis.conf"
    CONF4="/usr/local/redis-cluster/${REDISPORT4}/redis.conf"
    CONF5="/usr/local/redis-cluster/${REDISPORT5}/redis.conf"
    CONF6="/usr/local/redis-cluster/${REDISPORT6}/redis.conf"
    case "$1" in
        start)
            if [ -f $PIDFILE ]
            then
                    echo "$PIDFILE exists, process is already running or crashed"
            else
                    echo "Starting Redis cluster server..."
                    $EXEC $CONF1 &
                    $EXEC $CONF2 &
                    $EXEC $CONF3 &
                    $EXEC $CONF4 &
                    $EXEC $CONF5 &
                    $EXEC $CONF6 &
                    echo "启动成功..."
            fi
            ;;
        stop)
            if [ ! -f $PIDFILE ]
            then
                    echo "$PIDFILE does not exist, process is not running"
            else
                    PID=$(cat $PIDFILE)
                    echo "Stopping ..."
                    $CLIEXEC -p $REDISPORT1 shutdown
                    $CLIEXEC -p $REDISPORT2 shutdown
                    $CLIEXEC -p $REDISPORT3 shutdown
                    $CLIEXEC -p $REDISPORT4 shutdown
                    $CLIEXEC -p $REDISPORT5 shutdown
                    $CLIEXEC -p $REDISPORT6 shutdown
                    while [ -x /proc/${PID} ]
                    do
                        echo "Waiting for Redis cluster to shutdown ..."
                        sleep 1
                    done
                    echo "Redis cluster stopped"
            fi
            ;;
        *)
            echo "Please use start or stop as first argument"
            ;;
    esac
    
    chmod a+x /etc/init.d/redis
    
    chkconfig --add redis
    chkconfig redis on


    写数据,查看集群状态

    redis-cli -c -p 7000
    set foo bar
    get foo

    重新分片实践

    cd /usr/local/redis/src/
    ./redis-trib.rb reshard 127.0.0.1:7000

    集群状态

    redis-cli -p 7000 cluster nodes | grep master

    故障转移

    redis-cli -p 7002 debug segfault

    查看状态

    redis-cli -p 7000 cluster nodes | grep master

    增加新的节点

    ./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000

    删除一个节点

    redis-trib del-node ip:port '<node-id>'

    # 删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点

    添加一个从节点

    ./redis-trib.rb add-node --slave --master-id $[nodeid] 127.0.0.1:7008 127.0.0.1:7000

    八:Python配置Redis集群

    一:安装

    pip install redis-py-cluster

    二:配置文件

    START_NODES =  [
         # redis的IP和端口
        {'host':'172.16.199.1','port':7000},
    
        {'host':'172.16.199.1','port':7001},
    
        {'host':'172.16.199.1','port':7002},
    
        {'host':'172.16.199.1','port':7003},
    
        {'host':'172.16.199.1','port':7004},
    
        {'host':'172.16.199.1','port':7005}
    ]

    三:使用方式

    from rediscluster import RedisCluster  # 导入集群类
    
    from django.conf import settings      # 导入配置文件中的集群节点
      
    
    def test_cluster():
        # 连接redis集群节点
        redis_cluster  = RedisCluster(startup_nodes=settings.START_NODES)
        redis_cluster.set('name','SR')
        
  • 相关阅读:
    黄聪:C#多线程教程(1):BeginInvoke和EndInvoke方法,解决主线程延时Thread.sleep柱塞问题(转)
    黄聪:C#类似Jquery的html解析类HtmlAgilityPack基础类介绍及运用
    黄聪:国内com域名转移到Godaddy详细教程(转)
    黄聪:Navicat for MySQL的1577错误解决
    黄聪:VPS配置Filezilla Server支持FTP的Passive被动模式(FTP连接不上怎么办?有详细教程)
    黄聪:Microsoft office 2013版下载、安装及破解工具下载破解教程(Windows Toolkit)
    黄聪:mysql搬家,直接复制data文件夹(*.MYD,*.MYI,innodb)出错,无法正常显示
    黄聪:WordPress默认编辑器可视化切换不见了,非插件导致消失问题
    黄聪:自定义WordPress顶部管理工具条的技巧(转)
    黄聪:VS2010中“新建项目”却没有“解决方案”节点,如何调出来
  • 原文地址:https://www.cnblogs.com/SR-Program/p/12446092.html
Copyright © 2011-2022 走看看