zoukankan      html  css  js  c++  java
  • Redis介绍

    1. Redis简单介绍及优点

      REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。Redis提供了一些丰富的数据结构,包括 lists, sets, ordered sets 以及 hashes ,当然还有和Memcached一样的 strings结构.Redis当然还包括了对这些数据结构的丰富操作。

      使用过memcached的都知道,用户只能用APPEND命令将数据添加到已有字符串的末尾。这很好!用户可以将元素追加到一个字符串的末尾,并将那个字符串当作列表来使用。但随后如何删除这些元素?memcached采用的办法是通过黑名单来隐藏列表里面的元素,从而避免对元素执行、更新、写入等操作。相反,Redis的List和SET予许用户直接添加或者删除元素。

      在数据库中的常见用法是存储长期的报告数据,并将这些报告数据用作固定时间范围内的聚合数据。收集这些数据的办法:现将各个行插入一个报告表里面,之后在通过扫描这些行来聚合数据。之所以使用插入行的方式来存储,是因为大部分数据库来说,插入行操作的执行速度非常快(插入行只会在硬盘末尾进行写入)。不过,对表里面进行更新确实一个速度非常慢的操作。因为这种更新除了会引起一次随机读之外,还可能引起一次随机写。而在redis里面,用户可以直接使用原子INCR命令及其变种来计算聚合数据,并因为REDIS将数据存储在内存里面,而且发送给Redis的命令请求不需要你经过典型的查询分析器和查询优化器进行处理。所以对Redis的数据执行随机写是非常迅速的。

      Redis 有三个主要使其有别于其它很多竞争对手的特点:

      • Redis是完全在内存中保存数据的数据库,使用磁盘只是为了持久性目的;
      • Redis相比许多键值数据存储系统有相对丰富的数据类型;
      • Redis可以将数据复制到任意数量的从服务器中;

     

    • Redis优点

    异常快速 : Redis是非常快的,每秒可以执行大约110000设置操作,81000个/每秒的读取操作。

    支持丰富的数据类型 : Redis支持最大多数开发人员已经知道如列表,集合,可排序集合,哈希等数据类型。

    这使得在应用中很容易解决的各种问题,因为我们知道哪些问题处理使用哪种数据类型更好解决。

    操作都是原子的 : 所有 Redis 的操作都是原子,从而确保当两个客户同时访问 Redis 服务器得到的是更新后的值(最新值)。

    MultiUtility工具:Redis是一个多功能实用工具,可以在很多如:缓存,消息传递队列中使用(Redis原生支持发布/订阅),在应用程序中,如:Web应用程序会话,网站页面点击数等任何短暂的数据;

     

    2. Redis与Memcached对比

      这两年 Redis火得可以,Redis也常常被当作 Memcached的挑战者被提到桌面上来。关于Redis与Memcached的比较更是比比皆是。然而,Redis真的在功能、性能以及内存使用效率上都超越了Memcached吗?

      没有必要过于关注性能,因为二者的性能都已经足够高了。由于Redis只使用单核,而Memcached可以使用多核,所以二者比较起来,平均每一个核上,Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis。虽然Redis最近也在存储大数据的性能上进行优化,但是比起Memcached,还是稍有逊色。说了这么多,结论是,无论你使用哪一个,每秒处理请求的次数都不会成为瓶颈。

      在内存使用效率上,如果使用简单的key-value存储,Memcached的内存利用率更高。而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。当然,这和你的应用场景和数据特性有关。

    如果你对数据持久化和数据同步有所要求,那么推荐你选择Redis。因为这两个特性Memcached都不具备。即使你只是希望在升级或者重启系统后缓存数据不会丢失,选择Redis也是明智的。

      当然,最后还得说到你的具体应用需求。Redis相比Memcached来说,拥有更多的数据结构,并支持更丰富的数据操作。通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果你需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。

      下面列出简单的对比图:


     

    3. Redis安装

    3.1 Redis安装

    • 安装

      因为yum安装的版本比较底,这里使用源码方式来安装。且,配置文件和安装路径比较清晰。

      解压压缩包

      编译及安装

    [root@CentOS1 redis-3.2.7]# make MALLOC=libc && make PREFIX=/usr/local/redis install

      以上语法为固定语法,不需要深究,有兴趣的查阅官方文档

     

    • 设置配置文件

      在解压缩的目录下会有一个默认的配置文件,将此文件拷贝至人性化识别的方式上面去。

      这里本人以端口号来命名配置文件。因为后期启动脚本需要找到此文件。

    [root@CentOS1 redis-3.2.7]# mkdir /etc/redis
    [root@CentOS1 redis-3.2.7]# cp redis.conf /etc/redis/6379.conf

      这里需要把监听IP更改以下,否则默认的127.0.0.1会让其它客户机无法连接。

    [root@CentOS1 redis]# sed -n '62p' /etc/redis/6379.conf 
    bind 192.168.100.20
    • 设置server 的方式控制

      在解压缩的目录下/tools/redis-3.2.7/utils/会有一个默认的配置文件,将此文件拷贝至/etc/init.d/redis下。

    [root@CentOS1 utils]# cp redis_init_script /etc/init.d/redis

      更改启动脚本,因为这里启动脚本都是默认参数,如果不更改,脚本找不到执行路径。

      注:这里的启动脚本仅支持start和stop。

    [root@CentOS1 utils]# head /etc/init.d/redis 
    #!/bin/sh
    #
    # Simple Redis init.d script conceived to work on Linux systems
    # as it does use of the /proc filesystem.
     
    REDISPORT=6379
    EXEC=/usr/local/redis/bin/redis-server
    CLIEXEC=/usr/local/redis/bin/redis-cli  
     PIDFILE=/var/run/redis_${REDISPORT}.pid
    • 设置chkconfig控制

      因为redis的脚本默认不支持chkconfig,所以这里需要自己更改一下。

    [root@CentOS1 utils]# head -4 /etc/init.d/redis 
    #!/bin/sh
    #
    # chkconfig: 2345 60 50
    # description: This is a chkconfig.
     
    添加进入系统服务
    [root@CentOS1 utils]# chkconfig --add redis
    [root@CentOS1 utils]# chkconfig redis on

    3.2 后台启动及启动服务

    • 更改配置

      如果直接启动默认配置,那么就不是后台启动,这里简单配置以下,将redis作为后台启动。

    [root@CentOS1 utils]# grep "daemonize yes" /etc/redis/6379.conf 
    daemonize yes
    • 启动服务

      这里就不使用server的方式,因为后面需要演示集群,所以这里直接使用指定配置文件来启动。

      首先为了方便,把redis常用命令创建快捷方式。

    [root@CentOS1 bin]# ln -s /usr/local/redis/bin/redis-cli /usr/local/bin/redis-cli
    [root@CentOS1 bin]# ln -s /usr/local/redis/bin/redis-server /usr/local/bin/redis-server

      现在启动服务

    [root@CentOS1 bin]# redis-server /etc/redis/6379.conf 
    [root@CentOS1 bin]# netstat -napt | grep :6379
    tcp        0      0 127.0.0.1:6379              0.0.0.0:*                   LISTEN      16730/redis-server

    3.3 Redis简单连接测试

    • 现在连接Redis
    [root@CentOS1 bin]# redis-cli -h 127.0.0.1 -p 6379
    127.0.0.1:6379>
    • 简单操作

      使用info命令,可以查看和memcached的信息

     

    3.4 开启log

      本步骤只需要更改以下配置文件,重启服务即可。

    [root@CentOS1 bin]# sed -n '163p' /etc/redis/6379.conf 
    logfile "/var/log/redis.log"

      重启服务

    [root@CentOS1 bin]# redis-cli -p 6379 shutdown
    [root@CentOS1 bin]# redis-server /etc/redis/6379.conf 
    [root@CentOS1 bin]# netstat -napt | grep 6379
    tcp        0      0 127.0.0.1:6379              0.0.0.0:*                   LISTEN      26337/redis-server

      查看log

      

    4. Redis数据类型

    Redis支持5种数据类型。

    • Strings - 字符串

      Redis的字符串是字节序列。在Redis中字符串是二进制安全的,这意味着他们有一个已知的长度,是没有任何特殊字符终止决定的,所以可以存储任何东西,最大长度可达512兆。

    127.0.0.1:6379> set name "lizexiong"
    OK
    127.0.0.1:6379> get name
    "lizexiong"

      在上面的例子使用Redis命令set和get,Redis的名称是lizexiong的键存储在Redis的字符串值。

      也可以使用append来追加值。

     

      INCR命令用于由一个递增key的整数值。如果该key不存在,它被设置为0执行操作之前。如果key包含了错误类型的值或包含不能被表示为整数,字符串,则返回错误。

      也可以使用incrby直接指定增加多少数值

     

      既然有递增,那么就会有递减。使用decr来递减。

      也可以使用decrby直接指定减少的数值

      也可以使用incrbyfloat设置小数类型

      获取字符串长度

      注:字符串值可以存储最大512兆字节的长度。

     

    • Hashes - 哈希值

      Redis的哈希键值对的集合。 Redis的哈希值是字符串字段和字符串值之间的映射,所以它们被用来表示对象。

    127.0.0.1:6379> hmset user username lizexiong password huawei age 25
    OK
    127.0.0.1:6379> hgetall user
    1) "username"
    2) "lizexiong"
    3) "password"
    4) "huawei"
    5) "age"
    6) "25"

      也可以这样设置

    127.0.0.1:6379> hmset user1 username wuxinzhe
    OK
    127.0.0.1:6379> hmset user1 password huawei
    OK
    127.0.0.1:6379> hmset user1 age 33
    OK
    127.0.0.1:6379> hgetall user1
    1) "username"
    2) "wuxinzhe"
    3) "age"
    4) "33"
    5) "password"
    6) "huawei"

      在上面的例子中的哈希数据类型,用于存储包含用户的基本信息用户的对象。这里HMSET,HEXTALL对于Redis 命令 user:1 是键。

      每个哈希可存储多达232 - 1个 字段 - 值对(超过4十亿)。

     

    • Lists - 列表

      Redis的列表是简单的字符串列表,排序插入顺序。可以添加元素到Redis列表的头部或尾部。

      简单来说就是可以向左向右写入数据,一般L开头的单词就是向左边,R开头的就是向右边。

      因为上述的写入顺序是往左写了3次,往右写了1次。现在的顺序应该是

      2   1   0  3

      现在使用llen来获取key的长度。

      还可以使用rpop来弹出一个值,弹出之后值就没有了

      弹出了最左边的2.

      列表的最大长度为232- 1元素(4294967295,每个列表中的元素超过4十亿)。

    • Sets - 集合

      Redis集合是字符串的无序集合。在Redis中可以添加,删除和测试文件是否存在在O(1)的时间复杂度的成员。

      判断以下集合元素是否存在

      可以看到有值的返回1,没有的返回0

     

      判断集合的差集

      可以看出是写在前面的减去后面的

       

      判断集合的交集

      查看集合的并集

     

    • 集合排序

      Redis的集合排序类似于Redis集合,字符串不重复的集合。不同的是,一个有序集合的每个成员关联分数,用于以便采取有序set命令,从最小的到最大的分数有关。虽然成员都是独一无二的,分数可能会重复。

      简单来说有序的集合,支持排序的集合就是给每个元素设一个分数来判断排序。

      获取一个范围

      现在在增加一个

     

    5. Redis基本文档参考

    • Redis

      Redis的keys命令用于管理键。使用Redis的keys命令语法如下所示:

      语法

    redis 127.0.0.1:6379> COMMAND KEY_NAME

      例子

    redis 127.0.0.1:6379> SET yiibai redis
    OK
    redis 127.0.0.1:6379> DEL yiibai
    (integer) 1

      在上面的例子中DEL是命令,而yiibai是键。如果键被删除那么输出该命令将是 (integer) 1,否则它是 (integer) 0

     

      Redis的键命令

      如下表显示键的一些基本命令:

    S.N. 命令 & 描述
    1 DEL key
    此命令删除键,如果存在
    2 DUMP key 
    该命令返回存储在指定键的值的序列化版本。
    3 EXISTS key 
    此命令检查该键是否存在。
    4 EXPIRE key seconds
    指定键的过期时间
    5 EXPIREAT key timestamp 
    指定的键过期时间。在这里,时间是在Unix时间戳格式
    6 PEXPIRE key milliseconds 
    设置键以毫秒为单位到期
    7 PEXPIREAT key milliseconds-timestamp 
    设置键在Unix时间戳指定为毫秒到期
    8 KEYS pattern 
    查找与指定模式匹配的所有键
    9 MOVE key db 
    移动键到另一个数据库
    10 PERSIST key 
    移除过期的键
    11 PTTL key 
    以毫秒为单位获取剩余时间的到期键。
    12 TTL key 
    获取键到期的剩余时间。
    13 RANDOMKEY 
    从Redis返回随机键
    14 RENAME key newkey 
    更改键的名称
    15 RENAMENX key newkey 
    重命名键,如果新的键不存在
    16 TYPE key 
    返回存储在键的数据类型的值。

     

    • Redis字符串 

      Redis字符串命令用于在Redis管理字符串值。使用Redis字符串命令的语法如下所示:

      语法

    redis 127.0.0.1:6379> COMMAND KEY_NAME

      例子

    redis 127.0.0.1:6379> SET yiibai redis
    OK
    redis 127.0.0.1:6379> GET yiibai
    "redis"

      在上面的例子中,set和get是命令,而yiibai是键。

     

      Redis字符串命令

      如下表显示一些在Redis管理字符串基本的命令:

    S.N. 命令 & 描述
    1 SET key value 
    此命令用于在指定键设置值
    2 GET key 
    键对应的值。
    3 GETRANGE key start end 
    得到字符串的子字符串存放在一个键
    4 GETSET key value
    设置键的字符串值,并返回旧值
    5 GETBIT key offset
    返回存储在键位值的字符串值的偏移
    6 MGET key1 [key2..]
    得到所有的给定键的值
    7 SETBIT key offset value
    设置或清除该位在存储在键的字符串值偏移
    8 SETEX key seconds value
    键到期时设置值
    9 SETNX key value
    设置键的值,只有当该键不存在
    10 SETRANGE key offset value
    覆盖字符串的一部分从指定键的偏移
    11 STRLEN key
    得到存储在键的值的长度
    12 MSET key value [key value ...]
    设置多个键和多个值
    13 MSETNX key value [key value ...] 
    设置多个键多个值,只有在当没有按键的存在时
    14 PSETEX key milliseconds value
    设置键的毫秒值和到期时间
    15 INCR key
    增加键的整数值一次
    16 INCRBY key increment
    由给定的数量递增键的整数值
    17 INCRBYFLOAT key increment
    由给定的数量递增键的浮点值
    18 DECR key
    递减键一次的整数值
    19 DECRBY key decrement
    由给定数目递减键的整数值
    20 APPEND key value
    追加值到一个键
    • Redis 哈希

      Redis Hashes是字符串字段和字符串值之间的映射(类似于PHP中的数组类型)。 因此,它们是表示对象的完美数据类型。

      在Redis中,每个哈希(散列)可以存储多达4亿个键-值对。

      示例

    redis 127.0.0.1:6379> HMSET myhash name "redis tutorial" 
    description "redis basic commands for caching" likes 20 visitors 23000 
    OK 
    127.0.0.1:6379> HGETALL myhash
    1) "field1"
    2) "Hello"
    3) "field2"
    4) "World"
    5) "name"
    6) "redis tutorial"

      在上面的例子中,在名称为’myhash‘的哈希中设置了Redis教程的详细信息(名称,描述,喜欢,访问者)。

     

      Redis哈希命令

      下表列出了与哈希/散列相关的一些基本命令。

    序号  命令 说明
    1 HDEL key field2 [field2] 删除一个或多个哈希字段。
    2 HEXISTS key field 判断是否存在散列字段。
    3 HGET key field 获取存储在指定键的哈希字段的值。
    4 HGETALL key 获取存储在指定键的哈希中的所有字段和值
    5 HINCRBY key field increment 将哈希字段的整数值按给定数字增加
    6 HINCRBYFLOAT key field increment 将哈希字段的浮点值按给定数值增加
    7 HKEYS key 获取哈希中的所有字段
    8 HLEN key 获取散列中的字段数量
    9 HMGET key field1 [field2] 获取所有给定哈希字段的值
    10 HMSET key field1 value1 [field2 value2 ] 为多个哈希字段分别设置它们的值
    11 HSET key field value 设置散列字段的字符串值
    12 HSETNX key field value 仅当字段不存在时,才设置散列字段的值
    13 HVALS key 获取哈希中的所有值

     

    • Redis列表

      Redis列表是简单的字符串列表,排序插入顺序。您可以在头部或列表的尾部Redis的列表添加元素。

      列表的最大长度为232 - 1 (每个列表超过4十亿元素4294967295)元素。

      例子

    redis 127.0.0.1:6379> LPUSH tutorials redis
    (integer) 1
    redis 127.0.0.1:6379> LPUSH tutorials mongodb
    (integer) 2
    redis 127.0.0.1:6379> LPUSH tutorials mysql
    (integer) 3
    redis 127.0.0.1:6379> LRANGE tutorials 0 10
     
    1) "mysql"
    2) "mongodb"
    3) "redis"

      在上述例子中的三个值被插入到redis的列表命名tutorials 使用LPUSH命令。

     

      Redis的命令列表

      如下表所示相关列出了一些基本的命令:

    S.N. 命令 & 描述
    1

    BLPOP key1 [key2 ] timeout 
    取出并获取列表中的第一个元素,或阻塞,直到有可用

    2 BRPOP key1 [key2 ] timeout 
    取出并获取列表中的最后一个元素,或阻塞,直到有可用
    3 BRPOPLPUSH source destination timeout 
    从列表中弹出一个值,它推到另一个列表并返回它;或阻塞,直到有可用
    4 LINDEX key index 
    从一个列表其索引获取对应的元素
    5 LINSERT key BEFORE|AFTER pivot value 
    在列表中的其他元素之后或之前插入一个元素
    6 LLEN key 
    获取列表的长度
    7 LPOP key 
    获取并取出列表中的第一个元素
    8 LPUSH key value1 [value2] 
    在前面加上一个或多个值的列表
    9 LPUSHX key value 
    在前面加上一个值列表,仅当列表中存在
    10 LRANGE key start stop 
    从一个列表获取各种元素
    11 LREM key count value 
    从列表中删除元素
    12 LSET key index value 
    在列表中的索引设置一个元素的值
    13 LTRIM key start stop 
    修剪列表到指定的范围内
    14 RPOP key 
    取出并获取列表中的最后一个元素
    15 RPOPLPUSH source destination 
    删除最后一个元素的列表,将其附加到另一个列表并返回它
    16 RPUSH key value1 [value2] 
    添加一个或多个值到列表
    17 RPUSHX key value 
    添加一个值列表,仅当列表中存在
    • Redis集合

      Redis集合是唯一字符串的无序集合。 唯一值表示集合中不允许键中有重复的数据。

      在Redis中设置添加,删除和测试成员的存在(恒定时间O(1),而不考虑集合中包含的元素数量)。列表的最大长度为2^32 - 1个元素(即4294967295,每组集合超过40亿个元素)。

     

      示例

    redis 127.0.0.1:6379> SADD myset "redis" 
    (integer) 1 
    redis 127.0.0.1:6379> SADD myset "mongodb" 
    (integer) 1 
    redis 127.0.0.1:6379> SADD myset "mysql" 
    (integer) 1 
    redis 127.0.0.1:6379> SADD myset "mysql" 
    (integer) 0 
    redis 127.0.0.1:6379> SMEMBERS "myset"  
    1) "mysql" 
    2) "mongodb" 
    3) "redis"

      在上面的示例中,通过命令SADD将三个值插入到名称为“myset”的Redis集合中。

     

      Redis集合命令

      下表列出了与集合相关的一些基本命令。

    序号 命令 说明
    1 SADD key member1 [member2] 将一个或多个成员添加到集合
    2 SCARD key 获取集合中的成员数
    3 SDIFF key1 [key2] 减去多个集合
    4 SDIFFSTORE destination key1 [key2] 减去多个集并将结果集存储在键中
    5 SINTER key1 [key2] 相交多个集合
    6 SINTERSTORE destination key1 [key2] 交叉多个集合并将结果集存储在键中
    7 SISMEMBER key member 判断确定给定值是否是集合的成员
    8 SMOVE source destination member 将成员从一个集合移动到另一个集合
    9 SPOP key 从集合中删除并返回随机成员
    10 SRANDMEMBER key [count] 从集合中获取一个或多个随机成员
    11 SREM key member1 [member2] 从集合中删除一个或多个成员
    12 SUNION key1 [key2] 添加多个集合
    13 SUNIONSTORE destination key1 [key2] 添加多个集并将结果集存储在键中
    14 SSCAN key cursor [MATCH pattern] [COUNT count] 递增地迭代集合中的元素

    6. Redis持久化 

    6.1 Redis持久化介绍

      Redis提供了多种不同级别的持久化方式:一种是RDB,另一种是AOF.

      RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。

      AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。你甚至可以关闭持久化功能,让数据只在服务器运行时存在。

      了解 RDB 持久化和 AOF 持久化之间的异同是非常重要的, 以下几个小节将详细地介绍这这两种持久化功能, 并对它们的相同和不同之处进行说明。

     

    • RDB 的优点

      RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。 这种文件非常适合用于进行备份: 比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。 这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。RDB 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心,或者亚马逊 S3 中。RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

     

    • RDB 的缺点

      如果你需要尽量避免在服务器故障时丢失数据,那么 RDB 不适合你。 虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率, 但是, 因为RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据。每次保存 RDB 的时候,Redis 都要 fork() 出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时, fork() 可能会非常耗时,造成服务器在某某毫秒内停止处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒。 虽然 AOF 重写也需要进行 fork() ,但无论 AOF 重写的执行间隔有多长,数据的耐久性都不会有任何损失。

     

    • AOF 的优点

      使用 AOF 持久化会让 Redis 变得非常耐久(much more durable):你可以设置不同的 fsync 策略,比如无 fsync ,每秒钟一次 fsync ,或者每次执行写入命令时 fsync 。 AOF 的默认策略为每秒钟 fsync 一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync 会在后台线程执行,所以主线程可以继续努力地处理命令请求)。AOF 文件是一个只进行追加操作的日志文件(append only log), 因此对 AOF 文件的写入不需要进行 seek , 即使日志因为某些原因而包含了未写入完整的命令(比如写入时磁盘已满,写入中途停机,等等), redis-check-aof 工具也可以轻易地修复这种问题。

      Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。

     

    • AOF 的缺点

      对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。AOF 在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。 (举个例子,阻塞命令 BRPOPLPUSH 就曾经引起过这样的 bug 。) 测试套件里为这种情况添加了测试: 它们会自动生成随机的、复杂的数据集, 并通过重新载入这些数据来确保一切正常。 虽然这种 bug 在 AOF 文件中并不常见, 但是对比来说, RDB 几乎是不可能出现这种 bug 的。

     

    • RDB 和 AOF ,我应该用哪一个?

      一般来说,如果想达到足以媲美 PostgreSQL 的数据安全性, 你应该同时使用两种持久化功能。如果你非常关心你的数据,但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。有很多用户都只使用 AOF 持久化, 但我们并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快, 除此之外, 使用 RDB 还可以避免之前提到的 AOF 程序的 bug 。因为以上提到的种种原因, 未来我们可能会将 AOF 和 RDB 整合成单个持久化模型。 (这是一个长期计划。)

     

    • RDB 快照

      在默认情况下, Redis 将数据库快照保存在名字为 dump.rdb 的二进制文件中。你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。你也可以通过调用 SAVE 或者 BGSAVE , 手动让 Redis 进行数据集保存操作。比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集:

      save 60 1000

      这种持久化方式被称为快照(snapshot)。

     

    • 快照的运作方式

      当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:

      Redis 调用 fork() ,同时拥有父进程和子进程。

      子进程将数据集写入到一个临时 RDB 文件中。

      当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

      这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益。

    只进行追加操作的文件(append-only file,AOF)

      快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。尽管对于某些程序来说, 数据的耐久性并不是最重要的考虑因素, 但是对于那些追求完全耐久能力(full durability)的程序来说, 快照功能就不太适用了。

      从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化。

      你可以通过修改配置文件来打开 AOF 功能:

      appendonly yes

      从现在开始, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。

      这样的话, 当 Redis 重新启时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。

     

    • AOF 重写

      因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。举个例子, 如果你对一个计数器调用了 100 次 INCR , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录(entry)。然而在实际上, 只使用一条 SET 命令已经足以保存计数器的当前值了, 其余 99 条记录实际上都是多余的。为了处理这种情况, Redis 支持一种有趣的特性: 可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。执行 BGREWRITEAOF 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。

     

    • AOF 有多耐久?

      你可以配置 Redis 多久才将数据 fsync 到磁盘一次。

      有三个选项:

      每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。

      每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。

      从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。

      推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

      总是 fsync 的策略在实际使用中非常慢, 即使在 Redis 2.0 对相关的程序进行了改进之后仍是如此 —— 频繁调用 fsync 注定了这种策略不可能快得起来。

     

    • 如果 AOF 文件出错了,怎么办?

      服务器可能在程序正在对 AOF 文件进行写入时停机, 如果停机造成了 AOF 文件出错(corrupt), 那么 Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被破坏。

     

    • 当发生这种情况时, 可以用以下方法来修复出错的 AOF 文件

      为现有的 AOF 文件创建一个备份。

      使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复。

    $ redis-check-aof --fix

      (可选)使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。

      重启 Redis 服务器,等待服务器载入修复后的 AOF 文件,并进行数据恢复。

      AOF 的运作方式:AOF 重写和 RDB 创建快照一样,都巧妙地利用了写时复制机制。

     

    • 以下是 AOF 重写的执行步骤

      Redis 执行 fork() ,现在同时拥有父进程和子进程。

      子进程开始将新 AOF 文件的内容写入到临时文件。对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾: 这样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。

      为最新的 dump.rdb 文件创建一个备份。

      将备份放到一个安全的地方。

      执行以下两条命令:

    redis-cli> CONFIG SET appendonly yes
    redis-cli> CONFIG SET save ""

      确保命令执行之后,数据库的键的数量没有改变。

      确保写命令会被正确地追加到 AOF 文件的末尾。

      执行的第一条命令开启了 AOF 功能: Redis 会阻塞直到初始 AOF 文件创建完成为止, 之后 Redis 会继续处理命令请求, 并开始将写入命令追加到 AOF 文件末尾。

      执行的第二条命令用于关闭 RDB 功能。 这一步是可选的, 如果你愿意的话, 也可以同时使用 RDB 和 AOF 这两种持久化功能。

      别忘了在 redis.conf 中打开 AOF 功能! 否则的话, 服务器重启之后, 之前通过 CONFIG SET 设置的配置就会被遗忘, 程序会按原来的配置来启动服务器。

     

    • RDB 和 AOF 之间的相互作用

      在版本号大于等于 2.4 的 Redis 中, BGSAVE 执行的过程中, 不可以执行 BGREWRITEAOF 。 反过来说, 在 BGREWRITEAOF 执行的过程中, 也不可以执行 BGSAVE 。

      这可以防止两个 Redis 后台进程同时对磁盘进行大量的 I/O 操作。

      如果 BGSAVE 正在执行, 并且用户显示地调用 BGREWRITEAOF 命令, 那么服务器将向用户回复一个 OK 状态, 并告知用户, BGREWRITEAOF 已经被预定执行: 一旦 BGSAVE 执行完毕, BGREWRITEAOF 就会正式开始。当 Redis 启动时, 如果 RDB 持久化和 AOF 持久化都被打开了, 那么程序会优先使用 AOF 文件来恢复数据集, 因为 AOF 文件所保存的数据通常是最完整的。

     

    • 备份 Redis 数据

      Redis 对于数据备份是非常友好的, 因为你可以在服务器运行的时候对 RDB 文件进行复制: RDB 文件一旦被创建, 就不会进行任何修改。 当服务器要创建一个新的 RDB 文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用  原子地用临时文件替换原来的 RDB 文件。这也就是说, 无论何时, 复制 RDB 文件都是绝对安全的。

     

    • RDB和AOF区别简单讲解

      RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。

      AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。

     

      RDB存在哪些优势呢?

    1. 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。
    2. 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
    3. 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。
    4. 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。

     

      RDB又存在哪些劣势呢?

    1. 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
    2. 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。

     

      AOF的优势有哪些呢?

    1. 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。
    2. 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。
    3. 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。
    4. AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。

     

      AOF的劣势有哪些呢?

    1. 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
    2. 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。

     

      二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。不过生产环境其实更多都是二者结合使用的。

     

    6.2 Redis持久化配置

    6.2.1 Redis持久化之rdb

      开启配置文件下面的三个参数。因为默认就是rdb的方式,所以这里不需要特别配置。

    [root@CentOS1 ~]# sed -n '202,204p' /etc/redis/6379.conf 
    save 900 1
    save 300 10
    save 60 10000

      以上表示的意思是,

      • 900秒之内对服务进行了至少一次修改
      • 300秒之内服务器进行了至少10次修改
      • 60秒之内对服务器进行了至少10000次修改。

     

      还需要配置rdb文件的存放位置。

      以上是rdb的文件名以及文件存放位置。

     

      现在重启服务。

    [root@CentOS1 redis]# mkdir /usr/local/redis/cjh
    [root@CentOS1 ~]# redis-cli -p 6379 shutdown
    [root@CentOS1 ~]# redis-server /etc/redis/6379.conf

     

    • 现在开始测试持久化

      1. set一个值,手动保存,重启服务查看key值是否还在。

      

      现在重启服务查看保存的值是否还在。

      这里有2种保存方式,一种是save,一种是bgsave:SAVE 和 BGSAVE 两个命令都会调用 rdbSave 函数,但它们调用的方式各有不同:

      • SAVE 直接调用 rdbSave ,阻塞 Redis 主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。
      • BGSAVE 则 fork 出一个子进程,子进程负责调用 rdbSave ,并在保存完成之后向主进程发送信号,通知保存已完成。 Redis 服务器在BGSAVE 执行期间仍然可以继续处理客户端的请求。

     

     2. kill程序和kill -9 程序区别

    • kill

      kill 程序会告诉程序关闭,所以,数据会保存。

      这里开启一个新窗口

      现在启动服务,查看,结果为数据还在。

     

    • Kill -9

      现在开启新窗口直接kill -9

      现在启动服务,查看,结果新增的数据没有了,因为kill -9 直接杀死程序,程序没有反应过来。

     

    6.2.2 Redis持久化之aof

      RDB最大的不足之处在于:一旦数据库出现问题,由于RDB文件中保存的数据并不是全新的。从上次RDB文件生成到Redis宕机,这段时间的数据全部丢掉了(因为刷写机制还没有出发)。

      AOF比RDB有更好的持久性。在使用AOF的时候,redis会将每一个收到的写命令都通过write()系统函数追加到aof文件中,类似于MySQL的binlog。当redis重启后,会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

      AOF的完全持久化方式同时也带来了另一个问题,持久化文件会变得越来越大。(比如我们调用INCR test命令100次,文件中就必须保存全部的100条命令,但其实99条都是多余的。因为要恢复数据库的状态其实文件中保存一条SET test 100就够了)。为了压缩AOF的持久化文件,Redis提供了bgrewriteaof命令。收到此命令后Redis将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,最后替换原来的文件,以此来实现控制AOF文件的增长。

    • 配置详解
    ############################## APPEND ONLY MODE ###############################  
    # 是否开启AOF,默认关闭(no)  
    appendonly yes  
      
    # 指定 AOF 文件名  
    appendfilename appendonly.aof  
      
    # Redis支持三种不同的刷写模式:  
    # appendfsync always #每次收到写命令就立即强制写入磁盘,是最有保证的完全的持久化,但速度也是最慢的,一般不推荐使用。  
    appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,是受推荐的方式。  
    # appendfsync no     #完全依赖OS的写入,一般为30秒左右一次,性能最好但是持久化最没有保证,不被推荐。  
      
    #在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。  
    #设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no  
    no-appendfsync-on-rewrite no   
      
    #当前AOF文件大小是上次日志重写得到AOF文件大小的二倍时,自动启动新的日志重写过程。  
    auto-aof-rewrite-percentage 100  
      
    #当前AOF文件启动新的日志重写过程的最小值,避免刚刚启动Reids时由于文件尺寸较小导致频繁的重写。  
    auto-aof-rewrite-min-size 64mb  

      现在重启服务

      重启之后出现文件。

      现在测试kill -9 文件是否还在。

      开启一个新窗口强制杀死

      然后重新启动服务查看,数据还在。

     

      关于redis的刷新模式和日志重写:

    由于写操作通常是有缓冲的,所以有可能AOF操作并没有写到硬盘中,一般可以通过fsync()来强制输出到硬盘中。而fsync()的频率可以通过配置文件中的flush策略来指定,可以选择每次事件循环写操作都强制fsync或者每秒fsync至少运行一次。

    当rewrite子进程开始后,父进程接受到的命令会添加到aof_rewrite_buf_blocks中,使得rewrite成功后,将这些命令添加到新文件中。在rewrite过程中,原来的AOF也可以选择是不是继续添加,由于存在性能上的问题,在rewrite过程中,如果fsync()继续执行,会导致IO性能受损影响Redis性能。所以一般情况下rewrite期间禁止fsync()到旧AOF文件。这策略可以在配置文件中修改。

     

    7. Redis 主从模式

    7.1 Redis 主从模式

    • Redis的同步原理

        这里首先需要说明的是,在Redis中配置Master-Slave模式真是太简单了。相信在阅读完这篇Blog之后你也可以轻松做到。这里我们还是先列出一些理论性的知识,后面给出实际操作的案例。

        下面的列表清楚的解释了Redis Replication的特点和优势。

    1). 同一个Master可以同步多个Slaves。

    2). Slave同样可以接受其它Slaves的连接和同步请求,这样可以有效的分载Master的同步压力。因此我们可以将Redis的Replication架构视为图结构。

    3). Master Server是以非阻塞的方式为Slaves提供服务。所以在Master-Slave同步期间,客户端仍然可以提交查询或修改请求。

    4). Slave Server同样是以非阻塞的方式完成数据同步。在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据。

    5). 为了分载Master的读操作压力,Slave服务器可以为客户端提供只读操作的服务,写服务仍然必须由Master来完成。即便如此,系统的伸缩性还是得到了很大的提高。

    6). Master可以将数据保存操作交给Slaves完成,从而避免了在Master中要有独立的进程来完成此操作。

     

    • Replication的工作原理

      在Slave启动并连接到Master之后,它将主动发送一个SYNC命令。此后Master将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次完全同步。而Slave服务器在接收到数据库文件数据之后将其存盘并加载到内存中。此后,Master继续将所有已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在本次执行这些数据修改命令,从而达到最终的数据同步。

      如果Master和Slave之间的链接出现断连现象,Slave可以自动重连Master,但是在连接成功之后,一次完全同步将被自动执行。

     

    • 主从模式需要注意的几点:
    1. 因为启动服务使用redis-server的方式,所以只需要重启一个配置文件即可。
    2. Bind 的绑定IP最好改成服务器IP,不要使用127.0.0.1,否则其它终端连接的时候无法连接。
    3. 从Redis的配置pid、端口、rdb、aof文件需要更改为主配置不同。

     

    7.2  配置主从模式

    • 配置

      创建从Redis配置文件

    [root@CentOS1 redis]# cp 6379.conf 6380.conf

      更改pid、端口号等

     

      添加成为主服务器的从服务器

    [root@CentOS1 redis]# sed -n '266,267p' /etc/redis/6380.conf 
    # slaveof <masterip> <masterport>
    slaveof 192.168.100.20 6379

      启动服务

      查看缓存文件是否生成

     

    • 测试

      开启窗口一和窗口二

      窗口一

      窗口二

     

      查看主从状态

      窗口一查看

      窗口二查看

     

    1. 测试主写数据,是否能在从看到数据。

      在从查看

      2. 测试先把主启动服务,写入数据到master上,在启动slave。

      启动从服务,然后查看log是否同步

     

    8. Redis 集群

      在设置时,各集群节点数据在set时是不一致的,但是在集群任何节点get之后,数据就可以同步了。

      Redis 在3.0版本前只支持单实例模式,虽然支持主从模式、哨兵模式部署来解决单点故障,但是现在互联网企业动辄大几百G的数据,可完全是没法满足业务的需求,所以,Redis 在 3.0 版本以后就推出了集群模式。redis3.0之前分片都是由一些软件程序来完成的,关于Redis分片的官方链接https://redis.io/topics/partitioning

     

    8.1  Redis集群架构及原理

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

     

    • Fail

    1. 节点的fail

    节点的fail是通过集群中超过半数的节点检测失效时才生效,这里会触发选举,将slave升级为maste

    2. 集群的fail

    如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成进群的slot映射[0-16383]不完成时进入fail状态.

    如果集群超过半数以上master挂掉,无论是否有slave集群进入fail状态.

     

    • redis-cluster投票:容错
    1. 领着投票过程是集群中所有master参与,如果半数以上master节点与其中一个master节点通信超时(cluster-node-timeout),认为当前master节点挂掉.
    2. 什么时候整个集群不可用(cluster_state:fail)?
    • 如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完成时进入fail状态. ps : redis-3.0.0.rc1加入cluster-require-full-coverage参数,默认关闭,打开集群兼容部分失败.
    • 如果集群超过半数以上master挂掉,无论是否有slave集群进入fail状态.

          ps:当集群不可用时,所有对集群的操作做都不可用,收到((error)CLUSTERDOWN The cluster is down)错误。

     

    8.2 安装及配置Redis集群

      这里使用一台机器做测试,只是在一台机器上启动多个redis进程。

    8.2.1 安装环境

    [root@CentOS1 cjh]# yum -y install ruby rubygems

      这里的rubygems是gem文件的管理工具,安装gem需要用到它,如gem install xxx.gem,之所以安装这个是因为,redis集群管理工具redis-trib.rb依赖ruby环境,ruby是一种面向对象的语言。redis-trib.rb在redis-3.2.3.tar.gz源码包中。

     

    8.2.2 安装gem文件

    [root@CentOS1 cjh]# gem install redis
    Successfully installed redis-3.3.3
    1 gem installed
    Installing ri documentation for redis-3.3.3...
    Installing RDoc documentation for redis-3.3.3...
    [root@CentOS1 cjh]# echo $?
    0

    8.2.3 创建安装节点

      Redis集群运行最起码要3个主节点。

      一个redis集群的搭建,最少需要6个节点,构成3组服务节点;每组服务节点包括两个节点(Master-Slave)

       建立配置文件,首先需要创建一个配置文件的模版文件。

    [root@CentOS1 cjh]# mkdir /redis
    [root@CentOS1 cjh]# mkdir –p  /redis/`seq 7001 7008`
    [root@CentOS1 redis]# sed -n '722,724p' /redis/6380.conf 
    cluster-enabled yes
    cluster-config-file nodes_6380.conf
    cluster-node-timeout 5000

    cluster-enabled yes 用于开启实例的集群模式。

    cluster-config-file nodes.conf 设定了保存节点配置文件的路径。

    cluster-node-timeout 5000

    [root@CentOS1 redis]# sed 's/6380/7001/g' /redis/6380.conf >> /redis/7001/7001.conf
    [root@CentOS1 redis]# sed 's/6380/7002/g' /redis/6380.conf >> /redis/7002/7002.conf
    [root@CentOS1 redis]# sed 's/6380/7003/g' /redis/6380.conf >> /redis/7003/7003.conf
    [root@CentOS1 redis]# sed 's/6380/7004/g' /redis/6380.conf >> /redis/7004/7004.conf
    [root@CentOS1 redis]# sed 's/6380/7005/g' /redis/6380.conf >> /redis/7005/7005.conf
    [root@CentOS1 redis]# sed 's/6380/7006/g' /redis/6380.conf >> /redis/7006/7006.conf
    [root@CentOS1 redis]# sed 's/6380/7007/g' /redis/6380.conf >> /redis/7007/7007.conf
    [root@CentOS1 redis]# sed 's/6380/7008/g' /redis/6380.conf >> /redis/7008/7008.conf

      启动所有服务

      这里写一个脚本来启动

      这里先启动6个,留2个节点后面做测试。

    [root@CentOS1 redis]# for i in `seq 1 6`; do redis-server /redis/700"$i"/700"$i".conf; done
    [root@CentOS1 redis]# netstat -napt | grep redis
    tcp        0      0 192.168.100.20:7004         0.0.0.0:*                   LISTEN      20966/redis-server  
    tcp        0      0 192.168.100.20:7005         0.0.0.0:*                   LISTEN      20968/redis-server  
    tcp        0      0 192.168.100.20:7006         0.0.0.0:*                   LISTEN      20972/redis-server  
    tcp        0      0 192.168.100.20:17001        0.0.0.0:*                   LISTEN      20096/redis-server  
    tcp        0      0 192.168.100.20:17002        0.0.0.0:*                   LISTEN      20958/redis-server  
    tcp        0      0 192.168.100.20:17003        0.0.0.0:*                   LISTEN      20962/redis-server  
    tcp        0      0 192.168.100.20:17004        0.0.0.0:*                   LISTEN      20966/redis-server  
    tcp        0      0 192.168.100.20:17005        0.0.0.0:*                   LISTEN      20968/redis-server  
    tcp        0      0 192.168.100.20:17006        0.0.0.0:*                   LISTEN      20972/redis-server  
    tcp        0      0 192.168.100.20:7001         0.0.0.0:*                   LISTEN      20096/redis-server  
    tcp        0      0 192.168.100.20:7002         0.0.0.0:*                   LISTEN      20958/redis-server  
    tcp        0      0 192.168.100.20:7003         0.0.0.0:*                   LISTEN      20962/redis-server

    8.2.4 管理命令介绍

      首先创建一个链接文件方便操作

    [root@CentOS1 redis]# ln -s /tools/redis-3.2.7/src/redis-trib.rb /usr/local/bin/redis-trib

      查看帮助

     

    8.2.5 创建集群

      执行以下命令会有提示,输入yes

      输入后就完成了

     

    8.2.6 登录集群

      这里登录多了一个-c的参数,集群登录直接任意一个节点一个端口即可

    [root@CentOS1 redis]# redis-cli -h 192.168.100.20 -p 7001 –c

    8.2.7 查看集群信息

    CLUSTER INFO 打印集群的信息

    CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。

    从下列信息中可以看出,已经建立了主从关系,前三个为主,后三个节点为从。且主已经分配了slot位。

     

    8.2.8 测试

      在节点7001上新建一个值,在其它节点查看是否同步。

    现在登录其它节点查看

    7003

    7004

      由上结果可以看出

      redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。(并不是每个节点数据都是相同的)

     

    8.2.9 新增节点

      本章任务:新增一个主节点,但是主节点默认是没有分配slot的,所以新建之后还要手动分配slot,然后在添加最后7008作为7007的从节点。

    注释:

    192.168.100.20:7007是新增的节点

    192.168.100.20:7001集群任一个任何一个旧节点

     

      重新给主节点分配slot, 主节点如果没有slots的话,存取数据就都不会被选中。

      因为输入信息较长,这里贴出重要部分

    # redis-trib.rb reshard 192.168.100.20:7007 //下面是主要过程  
      
    How many slots do you want to move (from 1 to 16384)? 2000 //设置slot数1000  
    What is the receiving node ID? 03ccad2ba5dd1e062464bc7590400441fafb63f2 //新节点node id  
    Please enter all the source node IDs.  
     Type 'all' to use all the nodes as source nodes for the hash slots.  
     Type 'done' once you entered all the source nodes IDs.  
    Source node #1:all //表示全部节点重新洗牌  
    Do you want to proceed with the proposed reshard plan (yes/no)? yes //确认重新分 

      检查以下集群的情况

      可以看出,重新洗牌之后并不是按照顺序划分的slot,且现在有4个主节点。

      现在新增节点,把7008作为7007的从节点。

    [root@CentOS1 ~]# redis-trib add-node 192.168.100.20:7008 192.168.100.20:7007

      新增加的节点默认会认为自己就是master节点。

      连接至7008将自己设置为7007的从节点。

     

    8.2.10 删除节点

      删除从节点

    [root@CentOS1 ~]# redis-trib del-node 192.168.100.20:7008 'adcc751aa827fd0e81d5f4172dcd2e302adc0e8a'
    >>> Removing node adcc751aa827fd0e81d5f4172dcd2e302adc0e8a from cluster 192.168.100.20:7008
    >>> Sending CLUSTER FORGET messages to the cluster...
    >>> SHUTDOWN the node.

      删除主节点

    如果主节点有从节点,将从节点转移到其他主节点

    如果主节点有slot,去掉分配的slot,然后在删除主节点

      由于输出信息较多,这里只贴出重要部分。

    # redis-trib.rb reshard 192.168.100.20:7007 //取消分配的slot,下面是主要过程  
      
    How many slots do you want to move (from 1 to 16384)? 2000 //被删除master的所有slot数量  
    What is the receiving node ID? be6fe677e977ad6c3602381e372abf9c414f8c0c //接收6378节点slot的master  
    Please enter all the source node IDs.  
     Type 'all' to use all the nodes as source nodes for the hash slots.  
     Type 'done' once you entered all the source nodes IDs.  
    Source node #1:03ccad2ba5dd1e062464bc7590400441fafb63f2 //被删除master的node-id  
    Source node #2:done   
     Do you want to proceed with the proposed reshard plan (yes/no)? yes //取消slot后,reshard

      在新增master节点时,也进行了这一步操作,当时是分配,现在去掉。反着的。

      现在删除主节点。

    [root@CentOS1 ~]# redis-trib del-node 192.168.100.20:7007 '0bbd61f00af24bd65849acd3db1065a0e480838e'
    >>> Removing node 0bbd61f00af24bd65849acd3db1065a0e480838e from cluster 192.168.100.20:7007
    >>> Sending CLUSTER FORGET messages to the cluster...
    >>> SHUTDOWN the node.

      查看节点状态

     

    8.2.11 Redis Cluster命令行

      这些命令是集群所独有的。执行上述命令要先登录

    //集群(cluster)  
    
    CLUSTER INFO 打印集群的信息  
    
    CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。   
    
      
    
    //节点(node)  
    
    CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。  
    
    CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。  
    
    CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。  
    
    CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。   
    
      
    
    //槽(slot)  
    
    CLUSTER ADDSLOTS <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。  
    
    CLUSTER DELSLOTS <slot> [slot ...] 移除一个或多个槽对当前节点的指派。  
    
    CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。  
    
    CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。  
    
    CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。  
    
    CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。  
    
    CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。   
    
      
    
    //键 (key)  
    
    CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。  
    
    CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。  
    
    CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。

     

    8.3 Redis 集群之Codis

    由于本章版本更新较快,没有非常详细的指导文档,本章暂缺。

     

    9. Redis 管理工具

    9.1 PHPredisadmin

      phpredisadmin下载地址:https://github.com/ErikDubbelboer/phpRedisAdmin

     

    • 安装

      因为是基于phpredisadmin是基于LAMP(完整的php服务)服务的,且软件只有在Hub方式有,这里直接clone即可。

      首先到/var/www/html目录,直接克隆即可。

    [root@CentOS1 html]# pwd
    /var/www/html
    [root@CentOS1 html]# git clone https://github.com/ErikDubbelboer/phpRedisAdmin.git
    [root@CentOS1 html]# cd phpRedisAdmin
    [root@CentOS1 phpRedisAdmin]# git clone https://github.com/nrk/predis.git vendor

     

    • 配置

      默认会有一个模版文件。

    [root@CentOS1 includes]# cp config.sample.inc.php config.inc.php

      有几个节点就像下图这样添加

      登录查看

     

    9.2 Rdbtools

    9.2.1 Rdbtools介绍

      解析redis的dump.rdb文件,分析内存,以JSON格式导出数据。|

      提供的功能有:

    1. 生成内存报告

    2. 转储文件到JSON

    3. 使用标准的diff工具比较两个dump文件

      Rdbtools是以python语言开发的。

    9.2.2 安装

      这里使用源码的方式安装。

      首先安装python的安装包,然后使用各种方式安装。

    [root@CentOS1 redis-rdb-tools-master]# yum -y install python-setuptools
    [root@CentOS1 tools]# wget https://github.com/sripathikrishnan/redis-rdb-tools/archive/master.zip
    [root@CentOS1 tools]# unzip master.zip
    [root@CentOS1 tools]# cd redis-rdb-tools-master/
    [root@CentOS1 redis-rdb-tools-master]# python setup.py install

     

    9.2.3 转换dump文件到JSON

      解析dump文件并以JSON格式标准输出

    [root@CentOS1 rdb]# rdb --command json /usr/local/redis/cjh/dump_7001.rdb 
    [{
    "name":"lizexiong",
    "name2":"lizexiong"}]

      只解析符合正则的keys

    [root@CentOS1 rdb]# rdb --command json --key "na*" /usr/local/redis/cjh/dump_7001.rdb
    [{
    "name":"lizexiong",
    "name2":"lizexiong"}]

    9.2.4 生成内存报告

      生成CSV格式的内存报告。包含的列有:数据库ID,数据类型,key,内存使用量(byte),编码。内存使用量包含key、value和其他值。

      注意:内存使用量是近似的。在一般情况下,略低于实际值。

      可以根据key或数据库ID或数据类型对报告的内容进行过滤。

      内存报告有助于检测是否是应用程序逻辑导致的内存泄露,也有助于优化reids内存使用情况。

    [root@CentOS1 rdb]# rdb -c memory /usr/local/redis/cjh/dump_7001.rdb > redis_memory_report.csv
    [root@CentOS1 rdb]# cat redis_memory_report.csv 
    database,type,key,size_in_bytes,encoding,num_elements,len_largest_element
    0,string,"name",80,string,9,9
    0,string,"name2",80,string,9,9

    9.2.5 单个key所使用的内存量

      有时候,需要查询某个key所使用的内存。如果全部导出来在查找将是很愚蠢且耗时的。对于这种情景,可以使用redis-memory-for-key命令。

      如果出现下面信息,需要安装redis模块。redis-memory-for-key依赖redis-py包。

    Traceback (most recent call last):
     File "/usr/local/python/bin/redis-memory-for-key", line 8, in
     load_entry_point('rdbtools==0.1.5', 'console_scripts', 'redis-memory-for-key')()
     from redis import StrictRedis
    ImportError: No module named redis
     
    # /usr/local/python/bin/pip install redis
    # /usr/local/python/bin/easy_install redis

      一般上述不需要安装。

    [root@CentOS1 rdb]# redis-memory-for-key -s 192.168.100.20 -p 7001 name
    Key    "name"
    Bytes    80
    Type    string

     

    9.2.6 比较RDB文件

      使用–command diff选项,并通过管道来进行排序。

    [root@CentOS1 rdb]# rdb --command diff /usr/local/redis/cjh/dump_7001.rdb | sort > dump1.txt
    [root@CentOS1 rdb]# rdb --command diff /usr/local/redis/cjh/dump_7002.rdb | sort > dump2.txt
    [root@CentOS1 rdb]# diff dump1.txt dump2.txt 
    1,2d0
    < db=0 "name2" -> "lizexiong"
    < db=0 "name" -> "lizexiong"

      使用kdiff3工具来进行比较,kdiff3是图形化的工具,比较直观。kdiff3工具比较两个或三个输入文件或目录。

     

      安装kdiff3需要安装epel源。

    [root@CentOS1 rdb]# yum install kdiff3
    [root@CentOS1 rdb]# kdiff3 dump1.txt dump2.txt 
    QFSFileEngine::open: No file name specified
    kdiff3: cannot connect to X server

      需要linux图形界面,这里就不演示了。

     

    10. Redis故障记录

      本章是在搭建Redis过程中出现的一些问题。

     

    10.1 Redis Cluster 节点没有自动分配slot问题

      在创建集群的过程中,6个节点创建为集群,但是第一个节点莫名其妙的掉线,没有分配slot,经过测试,而且在其它节点和在本节点上查询ID值不相同。

      解决办法可以这么尝试,在节点的nodes.conf里自己编写节点配置信息。或者删除所有节点文件,重新创建可解决。

     

    以下为网上的文档得出的启发。

    只需要看第4标题部分。

    1. Linux系统配置
    
    1.1. vm.overcommit_memory设置
    
    overcommit_memory文件指定了内核针对内存分配的策略,其值可以是0、1、2。
    
    0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
    
    1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
    
    2, 表示内核允许分配超过所有物理内存和交换空间总和的内存
    
    jenkins_service@jenkinsservice:~/redis-3.0.1$ sudo sysctl vm.overcommit_memory=1
    
    vm.overcommit_memory = 1
    
    1.2. Transparent Huge Pages开启
    
    THP(Transparent Huge Pages)是一个使管理Huge Pages自动化的抽象层。
    
    目前需要注意的是,由于实现方式问题,THP会造成内存锁影响性能,尤其是在程序不是专门为大内内存页开发的时候,简单介绍如下:
    
    操作系统后台有一个叫做khugepaged的进程,它会一直扫描所有进程占用的内存,在可能的情况下会把4kpage交换为Huge Pages,在这个过程中,对于操作的内存的各种分配活动都需要各种内存锁,直接影响程序的内存访问性能,并且,这个过程对于应用是透明的,在应用层面不可控制,对于专门为4k page优化的程序来说,可能会造成随机的性能下降现象。
    
    Redis Cluster 命令行
    
    //集群(cluster)
    
    CLUSTER INFO 打印集群的信息  
    
    CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。   
    
      
    
    //节点(node)  
    
    CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。  
    
    CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。  
    
    CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。  
    
    CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。   
    
      
    
    //槽(slot)  
    
    CLUSTER ADDSLOTS <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。  
    
    CLUSTER DELSLOTS <slot> [slot ...] 移除一个或多个槽对当前节点的指派。  
    
    CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。  
    
    CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。  
    
    CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。  
    
    CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。  
    
    CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。   
    
      
    
    //键 (key)  
    
    CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。  
    
    CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。  
    
    CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。  
    
    2. 配置文件
    
    开启cluster的redis必须是空服务器
    
    修改redis.conf开启cluster
    
     
    
    设置3个cluster
    
    10.24.6.7:6379
    
    10.24.6.4:6379
    
    10.24.6.6:6379
    
    3. 查看初始redis集群状态
    
    启动三个节点上的Redis服务器。此时,三个Redis服务器节点均会以Redis Cluster的方式开始运行,但并没有自动构建集群,因为三者还处于“我不认识你,你不属于我”的状态,它们每个都是孤零零的Redis节点,或者是只包含了一个节点的集群。我们可以通过Redis客户端连接到服务器查看它们的状态,图一给出了状态查询方法和查询结果,其中cluster nodes命令用于查看当前Redis节点所属的Redis集群中的所有节点,而cluster info则用于查看当前Redis节点所属的Redis集群的整体状态。由图中我们可以看到,Redis集群中仅包含一个Redis节点,也就是当前节点,整个集群的状态是fail。
    
     
    
    4. 分配hash slot
    
    通过上面的操作,我们已经将三个各自为政的Redis节点规划到一个相同的集群中,那么我们现在是否就已经完成了集群搭建的所有工作了呢?非也!通过图二中对集群状态的查看我们可以知道,当前集群的状态还是fail,此时的Redis集群是不工作的,无法处理任何Redis命令。那么集群的状态为什么还是fail呢?本博主通过查看官方文档说明找到了原因所在,现摘录原文如下:
    
    The FAIL state for the cluster happens in two cases.
    
    1) If at least one hash slot is not served as the node serving it currently is in FAIL state.
    
    2) If we are not able to reach the majority of masters (that is, if the majorify of masters are simply in PFAIL state, it is enough for the node to enter FAIL mode).
    
    很明显,导致我们的集群处于fail状态的原因不是第二个条,也就是说至少有一个hash slot没有被服务!稍微考虑一下,可不是!何止有一个hash slot没有被服务,压根儿就没有Redis节点为任何hash slot服务!众所周知,Redis Cluster通过hash slot将数据根据主键来分区,所以一条key-value数据会根据算法自动映射到一个hash slot,但是一个hash slot存储在哪个Redis节点上并不是自动映射的,是需要集群管理者自行分配的。那么我们需要为多少个hash slot分配Redis节点呢?根据源码可知是16384个,即我们要将16384个hash slot分配到集群内的三个节点上。Redis中用于分配hash slot的命令有很多,其中包括cluster addslots、cluster delslots和cluster setslot。鉴于我们现在是集群的初始化阶段,所以我们可以选择cluster addslots来分配hash slot,该命令的语法为cluster addslots slot1 [slot2] ... [slotN]。
    
    4.1. nodes-6379.conf分配
    
    每个redis客户端单独分配自己负责的部分
    
    修改内容如下:cda76a0a094d2ce624e33bed7f3c75689a4128fd :0 myself,master - 0 0 connected 0-5000 (注意是在自身节点的描述,也就是包含了myself那一行的后面追加hash slot的范围)。类似的,Redis Cluster Node2上nodes-6379.conf文件中追加 5001-10000 ,Redis Cluster Node3上nodes-6379.conf文件中追加 10001-16383 。经过这样的配置后,Redis Cluster Node1负责存储0至5000之间的所有hash slots,Redis Cluster Node2负责存储5001至10000之间的所有hash slots,Redis Cluster Node3负责存储10001至16383的所有hash slots。
    
     
    
    4.2. Redis cluster 命令分配
    
     
    
    5. 搭建Redis集群
    
    这里所谓的搭建集群,说白了就是让之前启动的三个Redis节点彼此连通,意识到彼此的存在,那么如何做到这一点呢?答案就是cluster meet命令。该命令的作用就是将当前节点主动介绍给另外一个节点认识,图二给出了cluster meet命令的执行方法和执行效果,由图中可知我们使用cluster meet命令分别将Redis Cluster Node1介绍给了Redis Cluster Node2(节点IP地址为192.168.32.3,运行端口为6379)和Redis Cluster Node3(节点IP地址为192.168.32.4,运行端口为6379),之后我们再次查看集群节点和集群状态就可以知道,三个节点已经成功合并到了同一个集群中。
    
     
    
    这里找到了3个节点
    
    查看10.24.6.6客户端
    
     
    
    至此,3个结点
    
     
    
    搭建完成标识:
    
     
    
    在集群状态显示为ok之后,我们就可以像在Redis单机版上一样执行Redis命令了。
    
    6. 测试
    
    6.1. 非集群模式
    
    6.1.1.  Redis-cli
    
     
    
     
    
    非集群模式客户端在cluster跳转时会提示MOVED错误
    
    6.1.2.  Redis客户端库
    
    from redis.sentinel import 
    
    Sentinel
    
    sentinel = Sentinel([(
    
    '10.24.6.7' , 26379 )], socket_timeout= 0.1 
    
    )
    
    master = sentinel.master_for(
    
    '10.24.6.5master' , socket_timeout= 0.1 
    
    )
    
    print 
    
    master
    
    master.set(
    
    'aaaaaaaaaaaaaaa' , 'bar' 
    
    )
    
    master.set(
    
    'bbbbbbbbbbbbbbbb' , 'bar' 
    
    )
    
    print master.get( 'aaaaaaaaaaaaaaa' 
    
    )
    
    print master.get( 'bbbbbbbbbbbbbbbb' )
    
    Traceback (most recent call last):
    
    File "E:/HomeInternet/server/utest_workspace/utest_utils/utest_unit/__init__.py", line 23, in <module>
    
    master.set('bbbbbbbbbbbbbbbb', 'bar')
    
    File "build\bdist.win32\egg\redis\client.py", line 1055, in set
    
    File "build\bdist.win32\egg\redis\client.py", line 565, in execute_command
    
    File "build\bdist.win32\egg\redis\client.py", line 577, in parse_response
    
    File "build\bdist.win32\egg\redis\sentinel.py", line 55, in read_response
    
    File "build\bdist.win32\egg\redis\connection.py", line 574, in read_response
    
    redis.exceptions.ResponseError: MOVED 9577 10.24.6.6:6379
    
    6.2. 集群模式(-C)
    
    6.2.1.  Redis-cli
    
     
    
    集群模式客户端在跳转时会自动进行结点转向
    
    6.2.2. Redis Cluster
    
    https://github.com/Grokzen/redis-py-cluster
    
    from rediscluster import 
    
    StrictRedisCluster
    
    startup_nodes = [{
    
    "host" : "10.24.6.7" , "port" : "6379" 
    
    }]
    
    rc = StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True)
    
    print rc.set( "bbbbbbbbbbbbbbbb" , "bar" 
    
    )
    
    True
    
    print rc.get( "bbbbbbbbbbbbbbbb" )
    
     
    
    6.2.3. Redis Sentinel + Cluster
    
    from redis.sentinel import 
    
    Sentinel
    
    from rediscluster import 
    
    StrictRedisCluster
    
    sentinel = Sentinel([(
    
    '10.24.6.7' , 26379 )], socket_timeout= 0.1 
    
    )
    
    ip, port = sentinel.discover_master(
    
    '10.24.6.5master' 
    
    )
    
    rc = StrictRedisCluster(host=ip, port=port, decode_responses=True)
    
    print rc.set( "bbbbbbbbbbbbbbbb" , "bar" 
    
    )
    
    print rc.get( "bbbbbbbbbbbbbbbb" )
    slot问题解决方式

     

    10.2 集群断电后节点无法连接

      应用场景为 三台机器, 一主一从在一台机器上,当断掉一主一从以后,再次开启的时候断掉的一主一从无法连接上集群。

      解决方法是因为断掉之后slot分配给了存货的master,只有重新添加节点,分配slot才能将节点加入集群。

     

    https://redis.io/topics/partitioning

    SISMEMBER key member

    作者:小家电维修

    相见有时,后会无期。

  • 相关阅读:
    ThreadLocal
    spring概述
    排序
    内存的分配原则
    常用概念比较
    垃圾回收机制
    java的内存模型
    对象的内存布局
    adb connect 和 install 通讯流程
    Android硬件抽象层(HAL)深入剖析(三)
  • 原文地址:https://www.cnblogs.com/lizexiong/p/14563586.html
Copyright © 2011-2022 走看看