redis入门(三)

[TOC]

redis入门(三)

目录

redis入门(一)
redis入门(二)
redis入门(三)

前言

在前两章介绍了Redis的一些常用的API与功能,在本章会对一些其他功能包括事务、脚本、Redis集群搭建工具以及集群动态扩容与故障转移方式进行讲解。

事务

在关系型数据库,我们可以通过事务(transaction)的方式执行数据库级别的原子性操作。在Redis中也提供简单的事务功能。
Redis通过MULTIEXECWATCH等命令来实现功能。它提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制。
将一组需要一起执行的命令放到MULTIEXEC两个命令之间。MULTI命令代表事务开始,EXEC命令代表事务结束,它们之间的命令是原子顺序执行的,在MULTI执行之后,的写命令会直接返回QUEUE,当输入EXEC后会将所有命令一起执行。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set a 1
QUEUED
127.0.0.1:6379> set b 2
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK

若不使用事务时,客户端发送的命令会立即被服务端执行。使用事务时,当客户端发送的命令是EXECDISCARDWATCHMULTI命令之一时,服务器立即执行该命令,若不是上述四个命令,则会将命令加入到一个事务队列中,然后向客户端返回QUEUE回复。

由于开启事务时命令不会直接被执行,而是直接入队,因此Redis也不会立即发现运行时错误(比如hash的键使用string的命令执行)。因此当事务中某条命令执行失败时,其他命令还是可以可以正常执行。因此使用EXECMULTI命令时Redis仅保证打包的若干条命令以原子性顺序执行,而不保证事务中的命令全部执行成功。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set a 5
QUEUED
127.0.0.1:6379> hset b n 1
QUEUED
127.0.0.1:6379> set c 2
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) OK

为了实现真正的事务,Redis引入了WATCH实现乐观锁。在MULTI命令执行之前,可以通过WATCH监控指定的键,若在EXEC提交事务之前,数据发生了变化,则事务执行失败。

客户端A

127.0.0.1:6379> WATCH a
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set b 1
QUEUED
127.0.0.1:6379> set a 6
QUEUED
127.0.0.1:6379> set c 3
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379>  

客户端B

127.0.0.1:6379>  set a 7
OK

时间点

时间序号 客户端A 客户端B
1 WATCH a
2 multi
3 set b 1
4 set a 6
5 set c 3 set a 7
6 exec

客户端B在客户端A执行WATCH之后exec命令提交前执行了一条SET命令,客户端A提交EXEC命令则会提交失败。

原理

  1. 每个Redis数据库都会有一个字典用于保存被监视的键,而字典的的值是一个链表。该列表记录了所有监视该键的客户端。因此Redis服务器就清楚的知道哪些键被哪些客户端监视了。
  2. 当被监视的键被修改时,会触发一个动作将被修改键的客户端的该键的“脏数据”标志打开,表示该键的事务已经被破坏。
  3. 当客户端提交事务的时候,服务器会判断这个客户端是否存在被监视的键打开了“脏数据”标志。若该标识被打开,则说明客户端所以监视的键已经被修改,服务器就会拒绝事务提交。

Lua脚本

Redis从2.6版本开始引入对Lua脚本的支持。

Lua语言是在1993年由巴西一个大学研究小组发明,其设计目标是作为嵌入式程序移植到其他应用程序,它是由C语言实现的。

在redis服务器中内嵌了一个Lua环境,在redis服务启动之前会对该Lua环境进行一些修改,确保Lua环境满足redis服务器的需要。

安装

在ubuntu可以通过以下命令下载

curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz
tar zxf lua-5.3.5.tar.gz
cd lua-5.3.5
make linux test

在我本地编译Lua时报错,可以参考编译lua-5.3.5时出错解决方法解决。

windows环境下安装可以参考Lua在Windows下的安装、配置、运行

由于redis中存在Lua环境,因此即使不在本地安装Lua环境redis也是可以正常执行Lua脚本的也没关系。

脚本命令

Redis提供了2个执行lua脚本的命令EVALEVALSHA

  1. EVAL

    命令格式为eval 脚本内容 key个数 key列表 参数列表

    127.0.0.1:6379> eval ' return KEYS[1] .. ARGV[1]' 1 hello world
    "helloworld"
    

    redis中key下标从1开始
    lua通过..链接两个字符串

    我们也可以通redis-cli --eval直接执行脚本文件
    return KEYS[1] .. ARGV[1]保存到文件中,命名为helloworld.lua
    通过--eval 脚本路径 key列表 , 参数列表

    注意key列表和参数列表中间的,左右两边至少都要有一个空格,否则会报错

    jake@Jake-PC:~/tool$ redis/src/redis-cli -p 26379 --eval lua-5.3.5/helloworld.lua hello , world
    "helloworld"
    
  2. EVALSHA
    当脚本比较大时,每次发送脚本会占用一定的网络带宽。redis提供了讲脚本缓存的方式减少脚本传输的开销。首先需要通过script load命令将lua脚本加载到redis服务端,获得到脚本的SHA1校验和。然后通过evalsha命令执行校验和的脚本。

    127.0.0.1:6379> script load 'return KEYS[1] .. ARGV[1]'
    "dc8235f4444d746adf3374579406c129fb1f0f0a"
    127.0.0.1:6379> evalsha dc8235f4444d746adf3374579406c129fb1f0f0a 1 hello world
    "helloworld"
    

    每个被EVAL执行成功过的lua脚本,在lua环境都会有与该脚本对应的lua函数。函数名为f_加四十位的SHA1校验和。

    function f_dc8235f4444d746adf3374579406c129fb1f0f0a()
        return KEYS[1] .. ARGV[1]
    end
    

    我们还可以将脚本文件内容进行加载,通过evalsha获取其SHA1校验和。在linux环境下可以通过cat读取文件内容,

    jake@Jake-PC:~/tool$ redis/src/redis-cli -a test1 script load "$(cat lua-5.3.5/helloworld.lua)"
    "dc8235f4444d746adf3374579406c129fb1f0f0a"
    

    需要使用$()或``将cat lua-5.3.5/helloworld.lua包起来

    在windows环境下使用powershell可以通过Get-Content读取文本

    PS C:\Users\Dm_ca> redis-cli -a test1 script load (Get-Content F:\Study\helloworld.lua)
    "dc8235f4444d746adf3374579406c129fb1f0f0a"
    
  3. lua和redis互操作

    由于redis支持调用Lua脚本,而且Lua存在调用redis的API,这样我们就可以将一系列Lua脚本以原子性的执行。在lua中可以通过redis.call(command,key[param1, param2…])调用redis命令。

    127.0.0.1:26379> eval 'return redis.call("set",KEYS[1],ARGV[1])' 1 "hello" , "redis"
    OK
    

    对于redis中调用lua更多细节可以看EVAL script

  4. SCRIPT EXISTS
    通过该命令输入SHA1校验和可以检查对应的脚本是否存在。

  5. SCRIPT FLUSH
    该命令用于清除服务器中所有和lua脚本相关的信息,并关闭当前lua环境重新创建一个新的lua环境

  6. SCRIPT KILL
    在每次执行lua脚本之前,redis服务器都会在lua环境中设置一个超时处理钩子,若脚本执行超过配置的lua-time-limit的时长时,可以通过该命令停止当前的lua脚本执行。

    若当前lua脚本有写入操作,则无法在使用该脚本停止执行。只能通过SHUTDOWN nosave命令关闭。

  7. 脚本复制
    当服务器开启了主从复制时,写命令的脚本也会复制到从服务器以确保从服务器的数据和主服务器一致。
    但是EVALSHA命令比较特殊,因为有可能主服务器加载了脚本,从服务器还没有来的及同步。所以会存在主服务器字典中存在函数缓存但是从服务器不存在的情况。因此当Redis要求主服务器在传播EVALSHA命令的时候,必须确保EVALSHA命令要执行的脚本已经被所有从服务器载入过,如果不能确保这一点的话,主服务器会将EVALSHA命令转换成一个等价的EVAL命令,然后通过传播EVAL命令来代替EVALSHA命令。

集群搭建工具

redis-trib.rb

在上一节我们讲解了集群搭建的原理和过程。但是一步步都采取纯手工搭建会不太方便,而且也容易出错。在redis5.0以前可以通过redis-trib.rb进行集群搭建。它是Ruby实现Redis集群管理工具。

Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。 Ruby 可运行于多种平台,如 Windows、MAC OS 和 UNIX 的各种版本。

下面我在windows平台上搭建集群。

  1. 准备ruby环境。
    在windows环境可以到RubyInstaller下载安装。
    下载安装完可以通过ruby -v确定是否安装成功,以及当前ruby版本号。

    安装完成会弹出一个框询问安装MSYS2,我们可以不需要。

  2. 安装rubygem redis依赖:

    C:\Users\Dm_ca>gem install redis
    Fetching redis-4.1.3.gem
    Successfully installed redis-4.1.3
    Parsing documentation for redis-4.1.3
    Installing ri documentation for redis-4.1.3
    Done installing documentation for redis after 2 seconds
    1 gem installed
    
  3. 下载redis-trib.rb
    从github上下载3.2或4.0版本redis的redis-trib.rb代码保存到文件redis-trib.rb中。

    4.0的redis-trib.rb做了一定的优化,尽可能让主从处于不同的主机,同时当创建集群时若主从处于同一个ip也会进行提示。
    5.0的redis-trib.rb已经不支持了,redis-cli已经集成了redis-trib.rb的功能,当使用redis-trib.rb时会提示使用redis-cli cluster执行。

  4. 创建7579~75846个端口的配置文件,启动6个redis服务,配置可以参考上一章的集群搭建配置

     start redis-server.exe redis-7579.conf
     start redis-server.exe redis-7580.conf
     start redis-server.exe redis-7581.conf
     start redis-server.exe redis-7582.conf
     start redis-server.exe redis-7583.conf
     start redis-server.exe redis-7584.conf
    

    为了方便暂时没有作为windows服务启动

  5. 通过命令ruby redis-trib.rb create --replicas <arg> host1:port1 ... hostN:portN命令创建集群,如ruby redis-trib.rb create --replicas 1 127.0.0.1:7579 127.0.0.1:7580 127.0.0.1:7581 127.0.0.1:7582 127.0.0.1:7583 127.0.0.1:7584

  6. F:\Study\redis\redis集群>ruby redis-trib.rb create --replicas 1 127.0.0.1:7579 127.0.0.1:7580 127.0.0.1:7581 127.0.0.1:7582 127.0.0.1:7583 127.0.0.1:7584
    >>> Creating cluster
    >>> Performing hash slots allocation on 6 nodes...
    Using 3 masters:
    127.0.0.1:7579
    127.0.0.1:7580
    127.0.0.1:7581
    Adding replica 127.0.0.1:7583 to 127.0.0.1:7579
    Adding replica 127.0.0.1:7584 to 127.0.0.1:7580
    Adding replica 127.0.0.1:7582 to 127.0.0.1:7581
    >>> Trying to optimize slaves allocation for anti-affinity
    [WARNING] Some slaves are in the same host as their master
    M: 4e4f38cce9a8dd1d7871e327e69c2a2556c90ad7 127.0.0.1:7579
    slots:0-5460 (5461 slots) master
    M: 426942a0f20ccbfa9d68c1b0809800c31d10c0ab 127.0.0.1:7580
    slots:5461-10922 (5462 slots) master
    M: 1149113de5253841923789e79c362ad745509f5c 127.0.0.1:7581
    slots:10923-16383 (5461 slots) master
    S: e7e172a7cba6e052d36d0a330225f48f3858fb72 127.0.0.1:7582
    replicates 1149113de5253841923789e79c362ad745509f5c
    S: 7fb04e281546d6f0d0e0a3a06b5f80b101eae00f 127.0.0.1:7583
    replicates 4e4f38cce9a8dd1d7871e327e69c2a2556c90ad7
    S: b872de59634dd245c0452b46832994bf04a6c08b 127.0.0.1:7584
    replicates 426942a0f20ccbfa9d68c1b0809800c31d10c0ab
    Can I set the above configuration? (type 'yes' to accept): yes
    >>> Nodes configuration updated
    >>> Assign a different config epoch to each node
    >>> Sending CLUSTER MEET messages to join the cluster
    Waiting for the cluster to join...
    >>> Performing Cluster Check (using node 127.0.0.1:7579)
    M: 4e4f38cce9a8dd1d7871e327e69c2a2556c90ad7 127.0.0.1:7579
    slots:0-5460 (5461 slots) master
    1 additional replica(s)
    M: 1149113de5253841923789e79c362ad745509f5c 127.0.0.1:7581
    slots:10923-16383 (5461 slots) master
    1 additional replica(s)
    S: 7fb04e281546d6f0d0e0a3a06b5f80b101eae00f 127.0.0.1:7583
    slots: (0 slots) slave
    replicates 4e4f38cce9a8dd1d7871e327e69c2a2556c90ad7
    S: b872de59634dd245c0452b46832994bf04a6c08b 127.0.0.1:7584
    slots: (0 slots) slave
    replicates 426942a0f20ccbfa9d68c1b0809800c31d10c0ab
    M: 426942a0f20ccbfa9d68c1b0809800c31d10c0ab 127.0.0.1:7580
    slots:5461-10922 (5462 slots) master
    1 additional replica(s)
    S: e7e172a7cba6e052d36d0a330225f48f3858fb72 127.0.0.1:7582
    slots: (0 slots) slave
    replicates 1149113de5253841923789e79c362ad745509f5c
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.
    

    由于我绑定ip没修改,主从使用的都是127.0.0.1,因此会有警告提示 [WARNING] Some slaves are in the same host as their master
    生产配置需要绑定实际的ip,同时将protected-mode设置为no,否则只允许本机访问。
    查看集群状态,可以看到已经存在三主三从,同时虚拟槽都自动分配了。

    F:\Study\redis\redis集群>redis-cli -p 7479 cluster nodes
    0f6cf326c23af6399e6c3bfc374b04efbac015d3 127.0.0.1:7381@17381 master - 0 1572935809989 3 connected 10923-16383
    96b98672b59fd85f8743fde5b354abdb38ee3b47 127.0.0.1:7479@17479 myself,slave 0f6cf326c23af6399e6c3bfc374b04efbac015d3 0 1572935809000 4 connected
    231ee8d2ea76e1c7fe2031c127b8a055be87a3f4 127.0.0.1:7379@17379 master - 0 1572935810997 1 connected 0-5460
    e4ce1b6f872c6f72f776d534ce1dc783a0cf3655 127.0.0.1:7480@17480 slave 231ee8d2ea76e1c7fe2031c127b8a055be87a3f4 0 1572935808000 1 connected
    a9a4296b46db50459c5efb00d205fff671c2bfd0 127.0.0.1:7380@17380 master - 0 1572935810000 2 connected 5461-10922
    dcae00d572280d795fcbc82b899f2f1a50f1397c 127.0.0.1:7481@17481 slave a9a4296b46db50459c5efb00d205fff671c2bfd0 0 1572935809000 6 connected
    

redis官方集群搭建

在redis5.0开始官方集成了redis-trib.rb。可以直接通过cluster create命令创建集群。

  1. 将六个redis服务启动

    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-server data/redis-7379.config
    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-server data/redis-7380.config
    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-server data/redis-7381.config
    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-server data/redis-7479.config
    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-server data/redis-7480.config
    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-server data/redis-7481.config
    
  2. 创建集群
    redis-cli --cluster create 127.0.0.1:7379 127.0.0.1:7380 127.0.0.1:7381 127.0.0.1:7479 127.0.0.1:7480 127.0.0.1:7481 --cluster-replicas 1
    在craete后面指定redis服务的ip和端口,最后通过--cluster-replicas表示每个主节点创建一个从节点。

    5.0的集群--cluster-replicas参数可以放到create后面也可以放到最后,但是4.0的集群--replicas需要放到create后面,不能放最后。

    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-cli --cluster create 127.0.0.1:7379 127.0.0.1:7380 127.0.0.1:7381 127.0.0.1:7479 127.0.0.1:7480 127.0.0.1:7481 --cluster-replicas 1
    >>> Performing hash slots allocation on 6 nodes...
    Master[0] -> Slots 0 - 5460
    Master[1] -> Slots 5461 - 10922
    Master[2] -> Slots 10923 - 16383
    Adding replica 127.0.0.1:7480 to 127.0.0.1:7379
    Adding replica 127.0.0.1:7481 to 127.0.0.1:7380
    Adding replica 127.0.0.1:7479 to 127.0.0.1:7381
    >>> Trying to optimize slaves allocation for anti-affinity
    [WARNING] Some slaves are in the same host as their master
    M: 5591d1f47c15f919e6c492325bca0a385b581471 127.0.0.1:7379
    slots:[0-5460] (5461 slots) master
    M: 157bee0bd158456fc7e27eb165299ed33df769a0 127.0.0.1:7380
    slots:[5461-10922] (5462 slots) master
    M: eb63ce6942fd606a81113fe07622908931356057 127.0.0.1:7381
    slots:[10923-16383] (5461 slots) master
    S: 3eb412b810c4bd9a3c0f4ab1f4af8ee03d06d818 127.0.0.1:7479
    replicates 5591d1f47c15f919e6c492325bca0a385b581471
    S: 30c2792fe726a9174c07f7d2db5704f5e9ef3b66 127.0.0.1:7480
    replicates 157bee0bd158456fc7e27eb165299ed33df769a0
    S: 56250f10afe111ce206169588300b39a6447ed91 127.0.0.1:7481
    replicates eb63ce6942fd606a81113fe07622908931356057
    Can I set the above configuration? (type 'yes' to accept): yes
    >>> Nodes configuration updated
    >>> Assign a different config epoch to each node
    >>> Sending CLUSTER MEET messages to join the cluster
    Waiting for the cluster to join
    .......
    >>> Performing Cluster Check (using node 127.0.0.1:7379)
    M: 5591d1f47c15f919e6c492325bca0a385b581471 127.0.0.1:7379
    slots:[0-5460] (5461 slots) master
    1 additional replica(s)
    S: 30c2792fe726a9174c07f7d2db5704f5e9ef3b66 127.0.0.1:7480
    slots: (0 slots) slave
    replicates 157bee0bd158456fc7e27eb165299ed33df769a0
    S: 56250f10afe111ce206169588300b39a6447ed91 127.0.0.1:7481
    slots: (0 slots) slave
    replicates eb63ce6942fd606a81113fe07622908931356057
    S: 3eb412b810c4bd9a3c0f4ab1f4af8ee03d06d818 127.0.0.1:7479
    slots: (0 slots) slave
    replicates 5591d1f47c15f919e6c492325bca0a385b581471
    M: 157bee0bd158456fc7e27eb165299ed33df769a0 127.0.0.1:7380
    slots:[5461-10922] (5462 slots) master
    1 additional replica(s)
    M: eb63ce6942fd606a81113fe07622908931356057 127.0.0.1:7381
    slots:[10923-16383] (5461 slots) master
    1 additional replica(s)
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.
    

    通过该命令可以自动集群握手并自动分配槽。

    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-cli -p 7379 cluster nodes
    30c2792fe726a9174c07f7d2db5704f5e9ef3b66 127.0.0.1:7480@17480 slave 157bee0bd158456fc7e27eb165299ed33df769a0 0 1572926323116 5 connected
    5591d1f47c15f919e6c492325bca0a385b581471 127.0.0.1:7379@17379 myself,master - 0 1572926322000 1 connected 0-5460       
    56250f10afe111ce206169588300b39a6447ed91 127.0.0.1:7481@17481 slave eb63ce6942fd606a81113fe07622908931356057 0 1572926320090 6 connected
    3eb412b810c4bd9a3c0f4ab1f4af8ee03d06d818 127.0.0.1:7479@17479 slave 5591d1f47c15f919e6c492325bca0a385b581471 0 1572926322107 4 connected
    157bee0bd158456fc7e27eb165299ed33df769a0 127.0.0.1:7380@17380 master - 0 1572926321098 2 connected 5461-10922
    eb63ce6942fd606a81113fe07622908931356057 127.0.0.1:7381@17381 master - 0 1572926320000 3 connected 10923-16383
    

集群横向扩展

由于使用redis-cli --clusterredis-trib.rb命令格式大同小异,下面我都在linux下使用redis-cli --cluster执行命令。

  1. 添加两个配置节点分别为7382和7482用于集群扩展。

  2. 启动新的节点

    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-server data/redis-7382.config
    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-server data/redis-7482.config
    
  3. 添加新的主节点到集群,使用--cluster add-node 新节点地址 集群节点地址添加新的节点

    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-cli --cluster add-node 127.0.0.1:7382 127.0.0.1:7379
    >>> Adding node 127.0.0.1:7382 to cluster 127.0.0.1:7379
    >>> Performing Cluster Check (using node 127.0.0.1:7379)
    M: 231ee8d2ea76e1c7fe2031c127b8a055be87a3f4 127.0.0.1:7379
    slots:[0-5460] (5461 slots) master
    1 additional replica(s)
    S: dcae00d572280d795fcbc82b899f2f1a50f1397c 127.0.0.1:7481
    slots: (0 slots) slave
    replicates a9a4296b46db50459c5efb00d205fff671c2bfd0
    S: 96b98672b59fd85f8743fde5b354abdb38ee3b47 127.0.0.1:7479
    slots: (0 slots) slave
    replicates 0f6cf326c23af6399e6c3bfc374b04efbac015d3
    M: 0f6cf326c23af6399e6c3bfc374b04efbac015d3 127.0.0.1:7381
    slots:[10923-16383] (5461 slots) master
    1 additional replica(s)
    M: a9a4296b46db50459c5efb00d205fff671c2bfd0 127.0.0.1:7380
    slots:[5461-10922] (5462 slots) master
    1 additional replica(s)
    S: e4ce1b6f872c6f72f776d534ce1dc783a0cf3655 127.0.0.1:7480
    slots: (0 slots) slave
    replicates 231ee8d2ea76e1c7fe2031c127b8a055be87a3f4
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.
    >>> Send CLUSTER MEET to node 127.0.0.1:7382 to make it join the cluster.
    [OK] New node added correctly.
    
  4. 添加新的从节点到集群,使用--cluster add-node --cluster-slave --cluster-master-id 主节点id 新的节点地址 集群节点地址添加新的节点

    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-cli --cluster add-node --cluster-slave --cluster-master-id d683040a8654a9ce994365d988ded03c03393135 127.0.0.1:7482 127.0.0.1:7379
    >>> Adding node 127.0.0.1:7482 to cluster 127.0.0.1:7379
    >>> Performing Cluster Check (using node 127.0.0.1:7379)
    M: 231ee8d2ea76e1c7fe2031c127b8a055be87a3f4 127.0.0.1:7379
    slots:[0-5460] (5461 slots) master
    1 additional replica(s)
    S: dcae00d572280d795fcbc82b899f2f1a50f1397c 127.0.0.1:7481
    slots: (0 slots) slave
    replicates a9a4296b46db50459c5efb00d205fff671c2bfd0
    S: 96b98672b59fd85f8743fde5b354abdb38ee3b47 127.0.0.1:7479
    slots: (0 slots) slave
    replicates 0f6cf326c23af6399e6c3bfc374b04efbac015d3
    M: 0f6cf326c23af6399e6c3bfc374b04efbac015d3 127.0.0.1:7381
    slots:[10923-16383] (5461 slots) master
    1 additional replica(s)
    M: a9a4296b46db50459c5efb00d205fff671c2bfd0 127.0.0.1:7380
    slots:[5461-10922] (5462 slots) master
    1 additional replica(s)
    S: e4ce1b6f872c6f72f776d534ce1dc783a0cf3655 127.0.0.1:7480
    slots: (0 slots) slave
    replicates 231ee8d2ea76e1c7fe2031c127b8a055be87a3f4
    M: d683040a8654a9ce994365d988ded03c03393135 127.0.0.1:7382
    slots: (0 slots) master
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.
    >>> Send CLUSTER MEET to node 127.0.0.1:7482 to make it join the cluster.
    Waiting for the cluster to join
    
    >>> Configure node as replica of 127.0.0.1:7382.
    

    现在我们新的两个redis服务已经加入到集群中,通过cluster nodes查看当前集群节点。

    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-cli -p 7382 cluster nodes
    231ee8d2ea76e1c7fe2031c127b8a055be87a3f4 127.0.0.1:7379@17379 master - 0 1572942882135 1 connected 0-5460
    4b3a42f105e56b00d5b55eec9877d759b52f17e3 127.0.0.1:7482@17482 slave d683040a8654a9ce994365d988ded03c03393135 0 1572942881000 0 connected
    0f6cf326c23af6399e6c3bfc374b04efbac015d3 127.0.0.1:7381@17381 master - 0 1572942883151 3 connected 10923-16383
    a9a4296b46db50459c5efb00d205fff671c2bfd0 127.0.0.1:7380@17380 master - 0 1572942879000 2 connected 5461-10922
    dcae00d572280d795fcbc82b899f2f1a50f1397c 127.0.0.1:7481@17481 slave a9a4296b46db50459c5efb00d205fff671c2bfd0 0 1572942881000 2 connected
    d683040a8654a9ce994365d988ded03c03393135 127.0.0.1:7382@17382 myself,master - 0 1572942880000 0 connected
    96b98672b59fd85f8743fde5b354abdb38ee3b47 127.0.0.1:7479@17479 slave 0f6cf326c23af6399e6c3bfc374b04efbac015d3 0 1572942881120 3 connected
    e4ce1b6f872c6f72f776d534ce1dc783a0cf3655 127.0.0.1:7480@17480 slave 231ee8d2ea76e1c7fe2031c127b8a055be87a3f4 0 1572942879000 1 connected
    
  5. 添加节点完成,此时我们需要重新分片,将虚拟槽分配给新的节点。在redis集群中可以使用2个命令进行槽分配。--cluster reshard--cluster rebalance。当我们需要集群扩容时,一般都希望槽可以平均分配,此时可以使用该命令;rebalance用于平衡集群节点虚拟槽数量,自动重新平均分配可以使用该命令。src/redis-cli --cluster rebalance 127.0.0.1:7379 --cluster-use-empty-masters,若没有添加cluster-use-empty-masters空槽的redis服务不会加入分配,由于我们需要进行集群扩容,因此需要加上该参数。

    参数 说明
    --cluster-weight <node1=w1...nodeN=wN> 指定集群节点的权重
    --cluster-use-empty-masters 设置可以让没有分配slot的主节点参与,默认不允许
    --cluster-timeout 设置migrate命令的超时时间
    --cluster-pipeline 定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10
    --cluster-threshold 迁移的slot阈值超过threshold,执行rebalance操作
    --cluster-replace 是否直接replace到目标节点,若节点存在重复key时,不指定该参数会报错。
    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-cli --cluster rebalance 127.0.0.1:7379 --cluster-use-empty-masters
    >>> Performing Cluster Check (using node 127.0.0.1:7379)
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.
    >>> Rebalancing across 4 nodes. Total weight = 4.00
    Moving 1366 slots from 127.0.0.1:7380 to 127.0.0.1:7382
    ######################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
    Moving 1365 slots from 127.0.0.1:7381 to 127.0.0.1:7382
    #####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
    Moving 1365 slots from 127.0.0.1:7379 to 127.0.0.1:7382
    #####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
    

关于集群详细参数解释可以参考redis cluster 集群搭建(增、删、改、查)

故障转移

当有某台redis服务不再使用或出现故障时,我们需要进行故障迁移。在集群搭建时我们需要进行集群握手,握手完成后进行虚拟槽分配。而在故障转移的步骤也相反,我们首先需要进行虚拟槽迁移,虚拟槽迁移时会将数据进行迁移。迁移完成后将故障节点从节点中以前。这一系列故障迁移动作都是在线的,不会对redis集群的服务造成影响。
我们可以通过--cluster reshard将该节点下的所有虚拟槽迁移到新的节点上。

参数 说明
--cluster-from 需要从哪些源节点上迁移slot,可从多个源节点完成迁移,以逗号隔开,传递的是节点的node id,还可以直接传递--from all,这样源节点就是集群的所有节点,不传递该参数的话,则会在迁移过程中提示用户输入
--cluster-to slot需要迁移的目的节点的node id,目的节点只能填写一个,不传递该参数的话,则会在迁移过程中提示用户输入
--cluster-slots 需要迁移的slot数量,不传递该参数的话,则会在迁移过程中提示用户输入。
--cluster-yes 指定迁移时的确认输入
--cluster-timeout 设置migrate命令的超时时间
--cluster-pipeline 定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10
--cluster-replace 是否直接replace到目标节点,若节点存在重复key时,不指定该参数会报错。
  1. 准备一个新的redis服务7383(也可以将这些虚拟槽迁移到其他的主上)。

  2. 启动服务src/redis-server data/redis-7383.config

  3. 执行src/redis-cli --cluster add-node 127.0.0.1:7383 127.0.0.1:7379,将7382设置为主库加入到集群。

  4. 开始槽迁移,src/redis-cli --cluster reshard 127.0.0.1:7379 --cluster-from 0a81b56b44e7974112534a596c9e2ef3ed8b4603 --cluster-to 756eb55a943453f87b49191f35c88271c650fb91

     jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-cli --cluster reshard 127.0.0.1:7379 --cluster-from 0a81b56b44e7974112534a596c9e2ef3ed8b4603 --cluster-to 756eb55a943453f87b49191f35c88271c650fb91
     >>> Performing Cluster Check (using node 127.0.0.1:7379)
     M: 9bc411a648c4a0dc1ff8644973ded10c21857109 127.0.0.1:7379
     slots:[1365-5460] (4096 slots) master
     1 additional replica(s)
     S: d14a7d117eff2798e3ca5aa8a9afc88a0dbbdab1 127.0.0.1:7482
     slots: (0 slots) slave
     replicates 0a81b56b44e7974112534a596c9e2ef3ed8b4603
     M: 3d0c5deba0cd2b441d04cf7abe9dbd7af36b1af3 127.0.0.1:7380
     slots:[6827-10922] (4096 slots) master
     1 additional replica(s)
     M: 0a81b56b44e7974112534a596c9e2ef3ed8b4603 127.0.0.1:7382
     slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
     1 additional replica(s)
     S: 7d2ab32bff9437b4fdd65ffe4011715569a45362 127.0.0.1:7481
     slots: (0 slots) slave
     replicates 3d0c5deba0cd2b441d04cf7abe9dbd7af36b1af3
     M: e5fb7a9da406787dffd80f847102e4405eaf013d 127.0.0.1:7381
     slots:[12288-16383] (4096 slots) master
     1 additional replica(s)
     M: 756eb55a943453f87b49191f35c88271c650fb91 127.0.0.1:7383
     slots: (0 slots) master
     S: 06c1040b46e733cda47265ec64d56fec86459237 127.0.0.1:7480
     slots: (0 slots) slave
     replicates 9bc411a648c4a0dc1ff8644973ded10c21857109
     S: da488721d9d3271b557b1dcbf1e1dba48df7a856 127.0.0.1:7479
     slots: (0 slots) slave
     replicates e5fb7a9da406787dffd80f847102e4405eaf013d
     [OK] All nodes agree about slots configuration.
     >>> Check for open slots...
     >>> Check slots coverage...
     [OK] All 16384 slots covered.
     How many slots do you want to move (from 1 to 16384)? 4097
    
     Ready to move 4097 slots.
     Source nodes:
         M: 0a81b56b44e7974112534a596c9e2ef3ed8b4603 127.0.0.1:7382
         slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
         1 additional replica(s)
     Destination node:
         M: 756eb55a943453f87b49191f35c88271c650fb91 127.0.0.1:7383
         slots: (0 slots) master
     Resharding plan:
         Moving slot 0 from 0a81b56b44e7974112534a596c9e2ef3ed8b4603
         Moving slot 1 from 0a81b56b44e7974112534a596c9e2ef3ed8b4603
         ...
         Moving slot 12286 from 127.0.0.1:7382 to 127.0.0.1:7383:
         Moving slot 12287 from 127.0.0.1:7382 to 127.0.0.1:7383:
    

    当没有输入槽的数量,会提示需要迁移的槽数量。

  5. 执行src/redis-cli -p 7482 cluster REPLICATE 756eb55a943453f87b49191f35c88271c650fb91,将7382的从库7482设置为7383的从。

  6. 现在就可以将7382的库去除了。集群会移除该节点,同时该节点也会关闭。

    jake@Jake-PC:~/tool/demo/redis-cluster/redis$ src/redis-cli --cluster del-node 127.0.0.1:7379 0a81b56b44e7974112534a596c9e2ef3ed8b4603
     >>> Removing node 0a81b56b44e7974112534a596c9e2ef3ed8b4603 from cluster 127.0.0.1:7379
     >>> Sending CLUSTER FORGET messages to the cluster...
     >>> SHUTDOWN the node.
    

redis管理

目前我们可以使用redis自带的客户端对集群进行动态横向扩展与故障迁移。当redis服务较少时可以使用这种方式,但是当redis服务较多时,通过手动横向扩展与故障迁移的方式的工作量就非常大了,同时我们可能还需要多大量的redis服务进行监控与预警,这时候我们可以写一些脚本来方便运维,甚至可以使用专业的redis管理平台提高生产力。对于redis管理平台暂时没有研究,知名的有redislivecachecolud等。有兴趣的同学可以自己看一下。

参考文档

  1. redis
  2. redis开发与运维
  3. 编译lua-5.3.5时出错解决方法
  4. redis-5.0.0基于Redis官方工具的集群搭建(排坑指南,从安装Redis开始)
  5. Windows下 搭建redis集群
  6. redis cluster 集群搭建(增、删、改、查)
  7. Linux—shell中$(( ))、\(( )、``与\)的区别
  8. Redis Cluster & HDFS & ClustrixDB Reshard/Rebalance
  9. Redis实用监控工具一览

20191127212134.png
微信扫一扫二维码关注订阅号杰哥技术分享
出处:https://www.cnblogs.com/Jack-Blog/p/11804743.html
作者:杰哥很忙
本文使用「CC BY 4.0」创作共享协议。欢迎转载,请在明显位置给出出处及链接。

posted @ 2019-11-06 14:38  杰哥很忙  阅读(1029)  评论(2编辑  收藏  举报