Redis-Cluster 分布式缓存

Aug 17, 2016


本文讲述如何使用Redis的集群来对key-value的数据进行分布式的缓存。

至于Redis的原理和集群的机制,本文不作论述,我也不太了解,本文专注于集群的部署和使用。

因此,本文的重点在于Redis集群的详细配置文件,以及详细的部署过程。

要点:

    1. Redis的通用配置 与 结点个性配置  
    
    2. 部署缓存集群  
    
    3. 主结点扩展 与 从结点扩展  
    
    4. 主结点移除 与 从结点移除  
    
    5. 数据迁移均衡  

一. 版本架构

    系统 : ubuntu15.10  

    版本 : redis-3.0.7-64bits  

    架构 : 三个主结点  

        ( 因为我是用作分布式缓存,所以没必要设置用来备份的从结点 )  
        ( 实际环境下不同主结点要部署在不同机子上 )  
        主结点A : 127.0.0.1:7001  
        主结点B : 127.0.0.1:7002  
    主结点C : 127.0.0.1:7003  

二. 所有结点的公共配置文件 common.conf

    daemonize yes  

            以后台方式运行  

    tcp-backlog 511  

            每个结点tcp最大连接数  

    timeout 0  

            客户端连接超时时间(秒),该段时间内客户端没有发出任何命令,则关闭该连接  
            0表示禁用此项设置  

    tcp-keepalive 60  

            定期向客户端发送心跳探测(秒)  

    loglevel notice  
    
    databases 2  

            数据库的数量,默认数据库编号0,可用select命令在连接时指定库id  
            强烈推荐使用时用不同的库存放不同类的信息  

    stop-writes-on-bgsave-error yes  

            持久化出错时,停止写操作  

    rdbcompression yes  
    
    rdbchecksum yes  
    
    slave-serve-stale-data yes  
    
    slave-read-only yes  

            从结点只能处理读请求  

    repl-diskless-sync no  
    
    repl-diskless-sync-delay 5  
    
    repl-disable-tcp-nodelay yes  
    
    slave-priority 100  
    
    slowlog-log-slower-than 10000  

            超过10ms的命令将被记录慢日志  

    slowlog-max-len 128  
    
    latency-monitor-threshold 0  
    
    notify-keyspace-events ""  

    save 900 1  

            每隔900s,存在1个key被修改,发起快照保存  

    save 300 100  

            每隔300s,存在100个key被修改,发起快照保存  

    save 60 10000  

            每隔60s,存在10000个key被修改,发起快照保存  

    appendonly no  

            禁用aof持久化  
            这里我是把集群用作分布式缓存,所以禁用了aof持久化  
            如果你需要持久化,那么设置appendonly yes  

    appendfsync everysec  
    
    no-appendfsync-on-rewrite yes  
    
    auto-aof-rewrite-min-size 64mb  
    
    lua-time-limit 5000  
    
    aof-rewrite-incremental-fsync yes  
    
    hash-max-ziplist-entries 512  
    
    hash-max-ziplist-value 64  
    
    list-max-ziplist-entries 512  
    
    list-max-ziplist-value 64  
    
    set-max-intset-entries 512  
    
    zset-max-ziplist-entries 128  
    
    zset-max-ziplist-value 64  
    
    hll-sparse-max-bytes 3000  
    
    activerehashing yes  
    
    client-output-buffer-limit normal 0 0 0  
    
    client-output-buffer-limit slave 256mb 64mb 60  
    
    client-output-buffer-limit pubsub 32mb 8mb 60  
    
    hz 10  
    
    cluster-enabled yes  

            启用集群  

    cluster-node-timeout 15000  

            集群结点间超时(微秒)  

    cluster-migration-barrier 2  

            当一个主结点拥有至少2个从结点时,能够把自己的1个从结点让给没有从结点的主结点  

    cluster-require-full-coverage yes  
    
    cluster-slave-validity-factor 10  

三. 主结点A的配置文件 master7001.conf

    include /home/seven/program/redis/conf/common.conf  
    
            引入结点公共配置  
    
    port 7001  
    
            此结点的端口  
    
    pidfile /home/seven/program/redis/pid/master7001.pid  
    
            此结点的pid进程文件(推荐绝对路径)  
    
    logfile /home/seven/program/redis/log/master7001.log  
    
            此结点的日志文件(推荐绝对路径)  
    
    cluster-config-file /home/seven/program/redis/auto/master7001.conf  
    
            此结点启动后生成的配置信息(不同于本身的配置文件,它是自动生成的)  
    
    dir /home/seven/program/redis/data/  
    
            此结点的数据文件目录(推荐绝对路径)  
    
    appendfilename master7001.aof  
    
            此结点的aof型持久化文件  
            (只需文件名,且完整路径是上面的dir加上这个,即/home/seven/program/redis/data/master7001.aof)  
    
    dbfilename master7001.rdb  
    
            此结点的rdb型持久化文件  
            (只需文件名,且完整路径是上面的dir加上这个,即/home/seven/program/redis/data/master7001.rdb)  
    
    maxmemory 64mb  
    
            此结点的内存分配  
    
    maxmemory-policy allkeys-lru  
    
            此结点的所有键值对均采用LRU置换算法  
    
    auto-aof-rewrite-percentage 80-100  

四. 主结点B,C的配置文件 master7002.conf master7003.conf

    主结点B,C的配置文件,与A的配置只是端口和路径变了  

五. 安装 ruby

    sudo apt-get update  
    
    sudo apt-get install ruby  
    
    ruby -v  

六. 安装 rubygems

    https://rubygems.org/pages/download  
    
            下载rubygems,然后解压,进入它的目录  
    
    ruby setup.rb  
    
            安装rubygems,此命令需要root或者管理员身份  
    
    sudo apt-get install gem  
    
            安装gem  
    
    vi /var/lib/locales/supported.d/local  
    
            如果gem安装失败,则修改这个文件,追加一行内容 zh_CN.UTF-8 UTF-8  
    
    sudo locale-gen  
    
            如果gem安装失败,则继续上一条命令后执行此命令  
    
    sudo dpkg-reconfigure locales  
    
            如果gem安装失败,则继续上一条命令后执行此命令  
    
    gem install redis  
    
            安装rubygems-reids,此命令需要root或者管理员身份  
            然而发现报错,类似While executing gem ... (Gem::RemoteFetcher::FetchError)  
            多半是由于GFW的问题,需要更换源的网址  
    
    gem source -r https://rubygems.org/  
    
            删除原来的源网址  
    
    gem source -a https://ruby.taobao.org/  
    
            增加新的源网址  
    
    gem source -l  
    
            列出当前所有的源网址  
    
    gem install redis  
    
            再次安装rubygems-redis,此命令需要root或者管理员身份,这次发现成功安装  

七. 启动脚本

init.sh : 禁用hugepage。另外这个脚本要以root方式运行,所以权限最好设置为700,所属组设置为root:root

    echo never > /sys/kernel/mm/transparent_hugepage/enabled  
    
    echo never > /sys/kernel/mm/transparent_hugepage/defrag  

start.sh : 各结点的启动脚本

    redis-server /home/seven/program/redis/conf/master7001.conf  

            指定配置文件,启动主结点A  

    redis-server /home/seven/program/redis/conf/master7002.conf  

            指定配置文件,启动主结点B  

    redis-server /home/seven/program/redis/conf/master7003.conf  

            指定配置文件,启动主结点C  

clusterset.sh : 初始化集群的脚本

    cd /home/seven/Downloads/redis/src  

            进入你的redis的src目录,即redis-trib.rb这个脚本的位置  

    ./redis-trib.rb create --replicas 0 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003  

            配置集群的信息  
            其中,replicas后面跟的0表示每个主结点有0个从结点,即此时没有从结点  
            再后面的三个字符串表示三个主结点的地址和端口  
            
            另外,如果你有备份的需求(一般当需要持久化的时候),比如你的每个主结点需要有一个从结点,加入有三个从结点,  
            它们的地址也是本地,端口分别是8001,8002,8003,那么修改后的命令是这样的  
            
            ./redis-trib.rb create --replicas 1  
                127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003  
                127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003  
                
                // 其中 --replicas 1 表示每个主结点有一个从结点,且之后写完主结点列表后依次把各主结点的从结点写上  

八. 启动集群

    su root  
    
            进入root身份,以便执行init.sh来禁用hugepage  
    
    ./init.sh  
    
            禁用hugepage,此脚本必须以root身份执行  
    
    exit  
    
            退出root身份,以便以非root身份来启动redis集群  
    
    ./start.sh  
    
            启动redis的各个结点  
    
    ./clusterset.sh  
    
            初始化集群配置  
            第二次启动集群的时候,是不需要执行这个脚本的,就算执行也会报错的,除非你把之前的数据删光了  
    
    cd /home/seven/Downloads/redis/src  
    
            进入你的redis的src目录,即redis-trib.rb这个脚本的位置  
    
    ./redis-trib.rb check 127.0.0.1:7001  
    
            通过主结点A来查看集群  
    
    ./redis-trib.rb check 127.0.0.1:7002  
    
            通过主结点B来查看集群  
    
    ./redis-trib.rb check 127.0.0.1:7003  
    
            通过主结点C来查看集群  

九. 检验集群

    redis-cli -c -h 127.0.0.1 -p 7001  
    
            连接本地的7001端口的redis结点  
            注意,一定要加 -c 参数,这样才是以集群方式登入  
    
    set name shangyang  
    
            通过本地7001端口的redis结点,设置一个键值对  
    
    get name  
    
            通过本地7001端口的redis结点,获取name的值  
    
    quit  
    
            退出redis-cli  
    
    redis-cli -c -h 127.0.0.1 -p 7002  
    
            连接本地的7002端口的redis结点  
    
    get name  
    
            通过本地7002端口的redis结点,获取name的值  
    
    set name yingquliang  
    
            通过本地7002端口的redis结点,设置name的值  
    
    quit  
    
            退出redis-cli  

十. 增加主结点

    "edit a new configure file"  
    
            编辑一个新的配置文件,例如 master7004.conf  
    
    redis-server /yourpath/master7004.conf  
    
            启动这个新的主结点  
    
    cd /home/seven/Downloads/redis/src  
    
            进入你的redis-trib.rb文件的目录  
    
    ./redis-trib.rb add-node 127.0.0.1:7004 127.0.0.1:7001  
    
            加入这个新的空结点到集群  
            第一个参数是这个新结点的ip:port  
            第二个参数是原来集群中任意一个结点的ip:port  
    
    ./redis-trib.rb reshard 127.0.0.1:7004  
    
            为这个新的空结点分配槽  
            ( 整个集群中主结点的总槽数是16384,尽量每个主结点的槽数差不多 )  
            如果不给新结点分配槽,该结点就无法存储数据  
            ( 新的集群有4个主结点,平均每个主结点16384/4=4096槽,新结点从原来的3个结点中每个拿过来4096/3=1365槽 )  
        
            接下来根据提示,选择: 要迁移的槽数量 + 要迁移到哪个结点上 + 从哪个结点上迁移  
            假设原来有N个结点,建议执行N次reshard命令,每次只从一个单独的结点上迁移过来16384/(N+1)/N个槽  
        
            这个命令一般用来进行在线的数据均衡  

十一. 增加从结点

    "edit a new configure file"  
    
            编辑一个新的配置文件,例如 slave8001.conf  
    
    redis-server /yourpath/slave8001.conf  
    
            启动这个新的从结点  
    
    cd /home/seven/Downloads/redis/src  
    
            进入你的redis-trib.rb文件的目录  
    
    ./redis-trib.rb add-node 127.0.0.1:8001 127.0.0.1:7001  
    
            加入这个新的空结点到集群  
            第一个参数是这个新结点的ip:port  
            第二个参数是原来集群中任意一个结点的ip:port  
    
    redis-cli -c -h 127.0.0.1 -p 8001  
    
            进入这个8001结点的shell  
            注意,要加 -c 参数,这样才是以集群方式登入  
    
    cluster replicate xxxxxxxxxxxxx  
    
            后面的参数表示这个从结点的主结点的id  
            关于id,可以用./redis-trib.rb check ip:port 来查看  
            在执行这条命令的时候,对应的主结点很可能无法提供服务,所以请在压力小的时候进行从结点的扩展  
            另外,从结点是没有槽的,因为从结点只是用作备份  

十二. 删除从结点

    cd /home/seven/Downloads/redis/src  

            进入你的redis-trib.rb文件的目录  

    ./redis-trib.rb del-node 127.0.0.1:8001 xxxxxxxxx  

            删除从结点  
            第一个参数是你要删除的从结点的ip:port  
            第二个参数是那个从结点的id,关于id,可以用./redis-trib.rb check ip:port 来查看  

    redis-cli -c -h 127.0.0.1 -p 8001 shutdown  

            关闭这个结点  
            既然它都从集群中移除了,再开着它也没用了,不如及早关闭它  

十三. 删除主结点

    删除主结点之前,必须把该主结点的槽迁移到其他的主结点上  
    以下便是迁移槽的步骤 :  
    
    ./redis-trib.rb reshard 127.0.0.1:7001  
    
            目标 : 把要删除的7004主结点上的部分槽迁移到7001主结点上  
            假设目前7004结点上有x个槽,删除7004后如果剩下n个主结点,那么建议迁移x/n个槽到7001结点上  
            同理迁移x/n个槽到7002,7003上  
    
    ./redis-trib.rb reshard 127.0.0.1:7002  
    
            目标 : 把要删除的7004主结点上的部分槽迁移到7002主结点上  
    
    ./redis-trib.rb reshard 127.0.0.1:7003  
    
            目标 : 把要删除的7004主结点上的部分槽迁移到7003主结点上  
    
    ./redis-trib.rb del-node 127.0.0.1:7004 xxxxxxxxx  
    
            删除空的主结点  
            第一个参数是你要删除的主结点的ip:port  
            第二个参数是那个主结点的id,关于id,可以用./redis-trib.rb check ip:port 来查看  

    redis-cli -c -h 127.0.0.1 -p 7001 shutdown  

            关闭这个结点  
            既然它都从集群中移除了,再开着它也没用了,不如及早关闭它  
    
    ./redis-trib.rb check 127.0.0.1:7001  
    
            通过7001结点来检查集群  
    
    ./redis-trib.rb info 127.0.0.1:7001  
    
            通过7001结点来查看集群信息