Redis详解

Redis 简介

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings)散列(hashes)列表(lists)集合(sets)有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。
Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

Redis与Memcache的区别

1)、存储方式: Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis有部份存在硬盘上,redis可以持久化其数据
2)、数据支持类型: memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型 ,提供list,set,zset,hash等数据结构的存储
3)、使用底层模型不同: 它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。 Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
4). value 值大小不同:Redis 最大可以达到 1gb;memcache 只有 1mb。
5)redis的速度比memcached快很多
6)Redis支持数据的备份,即master-slave模式的数据备份。

数据类型

前面介绍到 redis 主要有String(字符串)Hash(哈希)List(列表)Set(集合)、**ZSet(有序集合)**等数据类型,下面一一举栗子介绍:
String(字符串)

string是redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。

string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。

string类型是Redis最基本的数据类型,一个键最大能存储512MB。

redis 127.0.0.1:6379> SET name "123"
OK
redis 127.0.0.1:6379> GET name
"123"

相关命令

SET key value                   设置key=value
GET key                         或者键key对应的值
GETRANGE key start end          得到字符串的子字符串存放在一个键
GETSET key value                设置键的字符串值,并返回旧值
GETBIT key offset               返回存储在键位值的字符串值的偏移
MGET key1 [key2..]              得到所有的给定键的值
SETBIT key offset value         设置或清除该位在存储在键的字符串值偏移
SETEX key seconds value         键到期时设置值
SETNX key value                 设置键的值,只有当该键不存在
SETRANGE key offset value       覆盖字符串的一部分从指定键的偏移
STRLEN key                      得到存储在键的值的长度
MSET key value [key value...]   设置多个键和多个值
MSETNX key value [key value...] 设置多个键多个值,只有在当没有按键的存在时
PSETEX key milliseconds value   设置键的毫秒值和到期时间
INCR key                        增加键的整数值一次
INCRBY key increment            由给定的数量递增键的整数值
INCRBYFLOAT key increment       由给定的数量递增键的浮点值
DECR key                        递减键一次的整数值
DECRBY key decrement            由给定数目递减键的整数值
APPEND key value                追加值到一个键

Hash(哈希)

Redis hash 是一个键值(key=>value)对集合。

Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

redis> HMSET myhash field1 "Hello" field2 "World"
"OK"
redis> HGET myhash field1
"Hello"
redis> HGET myhash field2
"World"

相关命令

HDEL key field[field...] 		删除对象的一个或几个属性域,不存在的属性将被忽略

HEXISTS key field 			查看对象是否存在该属性域

HGET key field 				获取对象中该field属性域的值

HGETALL key 				获取对象的所有属性域和值

HINCRBY key field value 		将该对象中指定域的值增加给定的value,原子自增操作,
只能是integer的属性值可以使用

HINCRBYFLOAT key field increment 	将该对象中指定域的值增加给定的浮点数

HKEYS key 				获取对象的所有属性字段

HVALS key 				获取对象的所有属性值

HLEN key 				获取对象的所有属性字段的总数

HMGET key field[field...] 		获取对象的一个或多个指定字段的值

HSET key field value 			设置对象指定字段的值

HMSET key field value [field value ...] 同时设置对象中一个或多个字段的值

HSETNX key field value 			只在对象不存在指定的字段时才设置字段的值

HSTRLEN key field 			返回对象指定field的value的字符串长度,如果该对象或者field不存在,返回0.

HSCAN key cursor [MATCH pattern] [COUNT count] 	类似SCAN命令

List(列表)

Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

redis 127.0.0.1:6379> lpush test redis
(integer) 1
redis 127.0.0.1:6379> lpush test mongodb
(integer) 2
redis 127.0.0.1:6379> lpush test rabitmq
(integer) 3
redis 127.0.0.1:6379> lrange test 0 10
1) "rabitmq"
2) "mongodb"
3) "redis"
redis 127.0.0.1:6379>

相关命令

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

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

BRPOPLPUSH source destination timeout 从列表中弹出一个值,它推到另一个列表并返回它;或阻塞,直到有可用

LINDEX key index                     从一个列表其索引获取对应的元素

LINSERT key BEFORE|AFTER pivot value 在列表中的其他元素之后或之前插入一个元素

LLEN key                             获取列表的长度

LPOP key                             获取并取出列表中的第一个元素

LPUSH key value1 [value2]            在前面加上一个或多个值的列表

LPUSHX key value                     在前面加上一个值列表,仅当列表中存在

LRANGE key start stop                从一个列表获取各种元素

LREM key count value                 从列表中删除元素

LSET key index value                 在列表中的索引设置一个元素的值

LTRIM key start stop                 修剪列表到指定的范围内

RPOP key                             取出并获取列表中的最后一个元素

RPOPLPUSH source destination         删除最后一个元素的列表,将其附加到另一个列表并返回它

RPUSH key value1 [value2]            添加一个或多个值到列表

RPUSHX key value                     添加一个值列表,仅当列表中存在

Set(集合)

Redis的Set是string类型的无序集合。

添加一个 string 元素到 key 对应的 set 集合中,成功返回1,如果元素已经在集合中返回 0,如果 key 对应的 set 不存在则返回错误。

redis 127.0.0.1:6379> sadd test redis
(integer) 1
redis 127.0.0.1:6379> sadd test mongodb
(integer) 1
redis 127.0.0.1:6379> sadd test rabitmq
(integer) 1
redis 127.0.0.1:6379> sadd test rabitmq
(integer) 0
redis 127.0.0.1:6379> smembers test 1) "redis"
2) "rabitmq"
3) "mongodb"

相关命令

SADD key member [member ...]                 添加一个或者多个元素到集合(set)里

SCARD key                                    获取集合里面的元素数量

SDIFF key [key ...]                          获得队列不存在的元素

SDIFFSTORE destination key [key ...]         获得队列不存在的元素,并存储在一个关键的结果集

SINTER key [key ...]                         获得两个集合的交集

SINTERSTORE destination key [key ...]        获得两个集合的交集,并存储在一个集合中

SISMEMBER key member                         确定一个给定的值是一个集合的成员

SMEMBERS key                                 获取集合里面的所有key

SMOVE source destination member              移动集合里面的一个key到另一个集合

SPOP key [count]                             获取并删除一个集合里面的元素

SRANDMEMBER key [count]                      从集合里面随机获取一个元素

SREM key member [member ...]                 从集合里删除一个或多个元素,不存在的元素会被忽略

SUNION key [key ...]                         添加多个set元素

SUNIONSTORE destination key [key ...]        合并set元素,并将结果存入新的set里面

SSCAN key cursor [MATCH pattern] [COUNT count]迭代set里面的元素

ZSet(有序集合)

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

添加元素到集合,元素在集合中存在则更新对应score

redis 127.0.0.1:6379> zadd test 0 redis
(integer) 1
redis 127.0.0.1:6379> zadd test 0 mongodb
(integer) 1
redis 127.0.0.1:6379> zadd test 0 rabitmq
(integer) 1
redis 127.0.0.1:6379> zadd test 0 rabitmq
(integer) 0
redis 127.0.0.1:6379> > ZRANGEBYSCORE test 0 1000
1) "mongodb"
2) "rabitmq"
3) "redis"

相关命令

ZADD key score1 member1 [score2 member2]     添加一个或多个成员到有序集合,或者如果它已经存在更新其分数

ZCARD key                                    得到的有序集合成员的数量

ZCOUNT key min max                           计算一个有序集合成员与给定值范围内的分数

ZINCRBY key increment member                 在有序集合增加成员的分数

ZINTERSTORE destination numkeys key [key ...]多重交叉排序集合,并存储生成一个新的键有序集合。

ZLEXCOUNT key min max                        计算一个给定的字典范围之间的有序集合成员的数量

ZRANGE key start stop [WITHSCORES]           由索引返回一个成员范围的有序集合(从低到高)

ZRANGEBYLEX key min max [LIMIT offset count] 返回一个成员范围的有序集合(由字典范围)

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT]返回有序集key中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员,有序集成员按 score 值递增(从小到大)次序排列

ZRANK key member                              确定成员的索引中有序集合

ZREM key member [member ...]                  从有序集合中删除一个或多个成员,不存在的成员将被忽略

ZREMRANGEBYLEX key min max                    删除所有成员在给定的字典范围之间的有序集合

ZREMRANGEBYRANK key start stop                在给定的索引之内删除所有成员的有序集合

ZREMRANGEBYSCORE key min max                  在给定的分数之内删除所有成员的有序集合

ZREVRANGE key start stop [WITHSCORES]         返回一个成员范围的有序集合,通过索引,以分数排序,从高分到低分

ZREVRANGEBYSCORE key max min [WITHSCORES]     返回一个成员范围的有序集合,以socre排序从高到低

ZREVRANK key member                           确定一个有序集合成员的索引,以分数排序,从高分到低分

ZSCORE key member                             获取给定成员相关联的分数在一个有序集合

ZUNIONSTORE destination numkeys key [key ...] 添加多个集排序,所得排序集合存储在一个新的键

ZSCAN key cursor [MATCH pattern] [COUNT count]增量迭代排序元素集和相关的分数

持久化

Redis提供了两种持久化方法,一种是RDB,这种方式是通过快照(snapshotting)的方式完成的。它可以将存在于某一时刻的所有数据都写入硬盘。另一种是只追加文件AOF(append-only file)它会将所有写命令记录在硬盘里。两者可以同时使用。

1、RDB

手动触发

  • SAVE:阻塞Redis的服务器进程及阻塞所有来自客户端的请求,所以放数据库数据较多
    时,应该避免使用该命令,直到RDB文件被创建完毕

  • BGSAVE:Fork出一个子进程来创建RDB文件,不阻塞服务器进程 。lastsave 指令可以查看最近的备份时间

  • 自动触发

    根据redis.conf配置里的save m n定时触发(用的是BGSAVE)

    主从复制时,主节点自动触发

    执行Debug Relaod

    执行Shutdown且没有开启AOF持久化

FLUSHALL命令
当执行FLUSHALL命令时,Redis会清除数据库中的所有数据。需要注意的是:不论清空数据库的过程是否触发 了自动快照的条件,只要自动快照条件不为空,Redis就会执行一次快照操作,当没有定义自动快照条件时,执行FLUSHALL命令不会进行快照操作。

执行复制

当设置了主从模式时,Redis会在复制初始化是进行自动快照。

在几秒内改动了多少数据就触发持久化
想禁用的话不设置save 或者save “”
默认如下:
save 900 1
save 300 10
save 60 10000
15分钟内改了1次 或 5分钟内改了10次 或 1分钟内改了10000次
备份进程出错主进程停止写入操作
stop-writes-on-bgsave-error yes
是否压缩rdb文件 推荐no 相对于硬盘成本cpu更值钱
rdbcompression yes
rdbchecksum
存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样会增大约10%的性能消耗,如果希望获取更大的性能提升,可以关闭此功能。

快照原理

Redis默认会将快照文件存储在Redis当前进程的工作目录的dump.rdb文

件中,可以通过配置文件中的dir和dbfilename两个参数分别指定快照

文件的存储路径和文件名,例如:

1 dbfilename dump.rdb

2 dir /opt/soft/redis-3.0.4/cache

快照执行的过程如下:

  1. Redis使用fork函数复制一份当前进程(父进程)的副本(子进

程);

  1. 父进程继续处理来自客户端的请求,子进程开始将内存中的数

据写入硬盘中的临时文件;

  1. 当子进程写完所有的数据后,用该临时文件替换旧的RDB文

件,至此,一次快照操作完成。
在这里插入图片描述

2、AOF

AOF方式在使用redis存储非临时数据时,一般都需要打开AOF持久化来降低进程终止导致的数据丢失,AOF可以将redis执行的每一条写命令追加到硬盘文件中,这已过程显然会降低redis的性能,但是大部分情况下这个影响是可以接受的,另外,使用较快的硬盘能提高AOF的性能。
AOF持久化选项

appendonly no ###是否进行AOF持久化
appendfaync everysec ###自动AOF间隔时长
no-appendfaync-on-rewrite no ###压缩时能否进行同步操作
auto-aof-rewrite-percentage 100 ###相比上一次重写之后体积大于一倍(100%)执行压缩操作
auto-aof-rewrite-min-size 64mb ###体积大于64mb时执行压缩操作

AOF重写
随着redis不断运行,AOF文件会非常大,这可能会占满硬盘空间和使还原操作执行时间非常长。可以向redsi发送BGREWRITEAOF命令重写AOF文件。也可以设置相关配置自动执行BGREWRITEAOF,当满足配置的条件时,自动进行AOF重写操作。配置如下:
1、 auto-aof-rewrite-percentage 100:目前的AOF文件的大小超过上一次重写时的AOF文件的百分之多少时再次进行重写,如果之前没有重写过,则以启动时AOF文件大小为依据
2、 auto-aof-rewrite-min-size 64mb:当AOF文件的大小大于64MB时才进行重写,因为如果AOF文件本来就很小时,有几个无效的命令也是无伤大雅的事情。这两个配置项通常一起使用。
3、另外可以手动执行BGREWRITEAOF命令主动让redis重写AOF文件。

同步硬盘数据

虽然每次执行更改数据库的内容时,AOF都会记录执行的命令,但是由于操作系统本身的硬盘缓存的缘故,AOF文件的内容并没有真正地写入硬盘,在默认情况下,操作系统会每隔30s将硬盘缓存中的数据同步到硬盘,但是为了防止系统异常退出而导致丢数据的情况发生,我们还可以在Redis的配置文件中配置这个同步的频率:
1 # appendfsync always:每次AOF写入一个命令都会执行同步操作,这是最安全也是最慢的方式;
2 appendfsync everysec :每秒钟进行一次同步操作,一般来说使用这种方式已经足够;(出厂默认配置)
3 # appendfsync no:表示不主动进行同步操作,这是最不安全的方式。

appendonly.aof文件损坏修复方法
appendonly.aof所在目录下会有 redis-check-aof文件,通过 redis-check-aof --fix appendonly.aof 命令 修复。
同理,也可用redis-check-rdb工具来修复dump.rdb

AOF劣势:
1)相同数据集的数据而言,aof文件要远大于rdb文件,回复速度慢于rdb
2)aof运行效率要慢于rdb,没秒同步策略效率较好, 不同步效率和rdb相同
在这里插入图片描述

3、RDB 与 AOF 总结

1)rdb 与 aof 文件可以共存, redis启动时会先读aof文件,若aof文件被破坏,则无法启动成功!
2)RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储
3)AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的树,AOF命令以redis协议追加保存每次写的操作到文件末尾。
4)Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大
5)只做缓存:如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式
6)同时开启两种持久化方式:在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。RDB更适合用于备份数据库(AOF在不断变化不好备份),快速重启,而且不会有AOF可能潜在的bug,留着作为一个万一的手段
7)性能建议:
在这里插入图片描述

事务

Redis事务概念
Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。

  • 批量操作在发送 EXEC 命令前被放入队列缓存。
  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

总结说:redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。

Redis事务的三个阶段:

  • 开始事务(MULTI)。
  • 命令入队。
  • 执行事务(EXEC)。

Redis事务没有隔离级别的概念:
  批量操作在发送 EXEC 命令前被放入队列缓存,并不会被实际执行,也就不存在事务内的查询要看到事务里的更新,事务外查询不能看到。
  
Redis不保证原子性:
  Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。
  注意:事务中的命令若是 “编译”错误,如 “getset 11”,会导致其他命令不被执行,若是“运行”错误,如“inscr a1”,a1 为“a”,则其余命令仍会被执行。所以redis是部分支持事务。

Redis事务相关命令:

	watch key1 key2 ... : 类似于乐观锁,在事务提交时,如果watch监控的多个KEY中任何KEY的值已经被其他客户端更改,则使用EXEC执行事务时,事务队列将不会被执行。
	multi : 标记一个事务块的开始( queued )
	exec : 执行所有事务块的命令 ( 一旦执行exec后,之前加的监控锁都会被取消掉 ) 
	discard : 取消事务,放弃事务块中的所有命令
	unwatch : 取消watch对所有key的监控

注意:一旦执行了exec,之前加了的监控锁都会被取消掉了

复制(Master/Slave)

1、是什么?

Redis复制指的就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slave机制,Master以写为主,Slave以读为主

2、能干嘛?

读写分离、容灾恢复

3、怎么玩?

3.1 配从(库)不配主(库)
3.2 从库配置命令:slaveof 主库IP 主库端口
从库每次与master断开后,都需重新连接,除非你配置进redis.conf文件
Info replication 查看当前服务器主从状态
3.3 常用三招

  • 一主多从
    a、设定从机后,主机有的都会复制一遍
    b、三个机子都赋值同一个:只有主机可以写
    c、主机 shutdown,从机数据还在的,角色还是slave(原地待命)。 主机恢复复后,一切照旧
    d、从机shutdown,然后又恢复后,则角色是 master

  • 薪火相传
    a、上一个Slave可以是下一个slave的Master,Slave同样可以接收其他slaves的连接和同步请求,那么该slave作为链条中下一个的master,可以有效减轻master的写压力
    b、中途变更转向:会清楚之前的数据,重新建立拷贝最新的Slaveof新主库IP新主库端口
    c、处于中间的服务器的角色是:slave

  • 反客为主
    a、主机shutdown后,通过slave no one 命令设置slave为master。 主机恢复后,另立山头。
    b、使当前数据库停止与其他数据的同步,转成主数据库

4、复制原理

4.1 旧版复制功能

Redis的复制功能分为**同步(sync)命令传播(command propagate)**两个操作:

  • 同步操作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态;
  • 命令传播操作则用于在主服务器的数据库状态被修改,导致主从服务器的数据库状态出现不一致时,让主从服务器的数据库重新回到一致状态。

同步
当客户端向从服务器发送SLAVEOF命令,要求从服务器复制主服务器时,从服务器首先需要执行同步操作,也即是,将从服务器的数据库状态更新至主服务器当前所处的数据库状态。

从服务器对主服务器的同步操作需要通过向主服务器发送SYNC命令来完成,以下是SYNC命令的执行步骤 1、从服务器向主服务器发送SYNC命令;
2、收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令;
3、当主服务器的BGSAVE命令执行完毕时,主服务器会将BGSAVE命令生成的RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。
4、主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器数据库当前所处的状态。

命令传播
在执行完同步操作之后,主从服务器之间数据库状态已经相同了。但这个状态并非一成不变,如果主服务器执行了写操作,那么主服务器的数据库状态就会修改,并导致主从服务器状态不再一致。

所以为了让主从服务器再次回到一致状态,主服务器需要对从服务器执行命令传播操作:主服务器会将自己执行的写命令,也即是造成主从服务器不一致的那条写命令,发送给从服务器执行,当从服务器执行了相同的写命令之后,主从服务器将再次回到一致状态。

旧版复制功能的缺陷
在Redis中,从服务器对主服务器的复制可以分为以下两种情况:

  • 初次复制:从服务器以前没有复制过任何主服务器,或者从服务器当前要复制的主服务器和上一次复制的主服务器不同;
  • 断线后重复制:处于命令传播阶段的主从服务器因为网络原因而中断了复制,但从服务器通过自动重连接重新连上了主服务器,并继续复制主服务器。

对于初次复制来说,旧版复制功能能够很好地完成任务,但对于断线后重复制来说,旧版复制功能虽然也能让主从服务器重新回到一致状态,但效率却非常低。

SYNC命令是非常消耗资源的,因为每次执行SYNC命令,主从服务器需要执行一下操作:

1、主服务器需要执行BGSAVE命令来生成RDB文件,这个生成操作会耗费主服务器大量的CPU、内存和磁盘I/O资源;
2、主服务器需要将自己生成的RDB文件发送给从服务器,这个发送操作会耗费主从服务器大量的网络资源(带宽和流量),并对主服务器响应命令请求的时间产生影响;
3、接收到RDB文件的从服务器需要载入主服务器发来的RDB文件,并且在载入期间,从服务器会因为阻塞而没办法处理命令请求。
SYNC是一个如此消耗资源的命令,所以Redis最好在真需要的时候才需要执行SYNC命令。

4.2 新版复制功能

Redis从2.8版本开始,使用PSYNC命令代替SYNC命令来执行复制时的同步操作。

PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partial resynchronization)两种模式:

  • 其中完整重同步用于处理初次复制情况:完整重同步的执行步骤和SYNC命令的执行步骤基本一样,它们都是通过让主服务器创建并发送RDB文件,以及向从服务器发送保存在缓冲区里面的写命令来进行同步;
  • 而部分重同步则用于处理断线后重复制情况:当从服务器在断线后重新连接主服务器时,如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器,从服务器只要接收并执行这些写命令,就可以将数据库更新至主服务器当前所处的状态。

部分重同步的实现
部分重同步功能由以下三个部分构成:

  • 主服务器的复制偏移量(replication offset)和从服务器的复制偏移量;
  • 主服务器的复制积压缓冲区(replication backlog);
  • 服务器的运行ID(run ID)。

复制偏移量
执行复制的双方——主服务器和从服务器会分别维护一个复制偏移量:

  • 主服务器每次向从服务器传播N个字节的数据时,就将自己的复制偏移量的值加上N;
  • 从服务器每次收到主服务器传播来的N个字节的数据时,就将自己的复制偏移量的值加上N;

通过对比主从服务器的复制偏移量,程序可以很容易地知道主从服务器是否处于一致状态:

  • 如果主从服务器处于一致状态,那么主从服务器两者的偏移量总是相同的;
  • 相反,如果主从服务器两者的偏移量并不相同,那么说明主从服务器并未处于一致状态。

复制积压缓冲区
复制积压缓冲区是由主服务器维护的一个固定长度(fixed-size)先进先出(FIFO)队列,默认大小为1MB。
和普通先进先出队列随着元素的增加和减少而动态调整长度不同,固定长度先进先出队列的长度是固定的,当入队元素的数量大于队列长度时,最先入队的元素会被弹出,而新元素会被放入队列。

当主服务器进行命令传播时,它不仅会将写命令发送给所有从服务器,还会将写命令入队到复制积压缓冲区里面,如图所示。
在这里插入图片描述
因此,主服务器的复制积压缓冲区里面会保存着一部分最近传播的写命令,并且复制积压缓冲区会为队列中的每个字节记录相应的复制偏移量。
当从服务器重新连上主服务器时,从服务器会通过PSYNC命令将自己的复制偏移量offset发送给主服务器,主服务器会根据这个复制偏移量来决定对从服务器执行何种同步操作:

  • 如果offset偏移量之后的数据(也即是偏移量offset+1开始的数据)仍然存在于复制积压缓冲区里面,那么主服务器将对从服务器执行部分重同步操作;
  • 相反,如果offset偏移量之后的数据已经不存在于复制积压缓冲区,那么主服务器将对从服务器执行完整重同步操作。

根据需要调整复制积压缓冲区的大小

Redis为复制积压缓冲区设置的默认大小为1MB,如果主服务器需要执行大量写命令,又或者主从服务器断线后重连接所需的时间比较长,那么这个大小也许并不合适。如果复制积压缓冲区的大小设置得不恰当,那么PSYNC命令的复制重同步模式就不能正常发挥作用,因此,正确估算和设置复制积压缓冲区的大小非常重要。
复制积压缓冲区的最小大小可以根据公式second*write_size_per_second来估算:

  • 其中second为从服务器断线后重新连接上主服务器所需的平均时间(以秒计算);
  • 而write_size_per_second则是主服务器平均每秒产生的写命令数据量(协议格式的写命令的长度总和);

例如,如果主服务器平均每秒产生1 MB的写数据,而从服务器断线之后平均要5秒才能重新连接上主服务器,那么复制积压缓冲区的大小就不能低于5MB。
为了安全起见,可以将复制积压缓冲区的大小设为2secondwrite_size_per_second,这样可以保证绝大部分断线情况都能用部分重同步来处理。
至于复制积压缓冲区大小的修改方法,可以参考配置文件中关于repl-backlog-size选项的说明。

服务器运行ID
除了复制偏移量和复制积压缓冲区之外,实现部分重同步还需要用到服务器运行ID(run ID):

每个Redis服务器,不论主服务器还是从服务,都会有自己的运行ID
运行ID在服务器启动时自动生成,由40个随机的十六进制字符组成,例如53b9b28df8042fdc9ab5e3fcbbbabff1d5dce2b3;
当从服务器对主服务器进行初次复制时,主服务器会将自己的运行ID传送给从服务器,而从服务器则会将这个运行ID保存起来(注意哦,是从服务器保存了主服务器的ID)。

当从服务器断线并重新连上一个主服务器时,从服务器将向当前连接的主服务器发送之前保存的运行ID:

  • 如果从服务器保存的运行ID和当前连接的主服务器的运行ID相同,那么说明从服务器断线之前复制的就是当前连接的这个主服务器,主服务器可以继续尝试执行部分重同步操作;
  • 相反地,如果从服务器保存的运行ID和当前连接的主服务器的运行ID并不相同,那么说明从服务器断线之前复制的主服务器并不是当前连接的这个主服务器,主服务器将对从服务器执行完整重同步操作。

5、哨兵模式(sentinel)

redis2.6以后提供了一个"哨兵"的机制。哨兵的含义就是监控redis系统的运行状态。可以启动多个哨兵,去监控redis数据库的运行状态。其主要功能有两点:
  a、监控所有节点数据库是否在正常运行。
  b、master数据库出现故障时,可以自动通过投票机制,从slave节点中选举新的master,实现将从数据库转换为主数据库的自动切换。
  一个一主多从的Redis系统中,可以使用多个哨兵进行监控任务以保证系统足够稳健。此时,不仅哨兵会同时监控主数据库和从数据库,哨兵之间也会相互监控。在这里,建议大家哨兵至少部署3个,并且使用奇数个哨兵。
  
Redis的哨兵(sentinel) 系统用于管理多个 Redis 服务器,该系统执行以下三个任务:
  a、监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常。
  b、提醒(Notification):当被监控的某个 Redis出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。
  c、自动故障迁移(Automatic failover):当一个Master不能正常工作时,哨兵(sentinel) 会开始一次自动故障迁移操作,它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其他Slave改为复制新的Master; 当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用Master代替失效Master。
  启动哨兵:在/usr/local/redis/conf(具体目录根据实际情况)下创建一个名为sentinel.conf的文件,并写入内容sentinel monitor 被监控数据库名字(自己起一个名字) 被监控在数据库IP 被监控数据库端口 1
上面最后一个数字1,表示主机挂掉后salve投票看让谁接替成为主机,得票数多的redis成为主机。

一主二从模式下: 对主机启动哨兵模式,主机shutdown后,哨兵自动指派从机中的一个为主机,其余的从机为新主机的从机。当原先的主机重启后,其角色变为为slave,其主机为新指派的机器。

注意:一组sentinel能同时监控多个Master

发布订阅

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
在这里插入图片描述
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
在这里插入图片描述
Redis 发布订阅命令
1、PSUBSCRIBE pattern [pattern …]:订阅一个或多个符合给定模式的频道。
2、PUBSUB subcommand [argument [argument …]]:查看订阅与发布系统状态。
3、PUBLISH channel message:将信息发送到指定的频道。
4、PUNSUBSCRIBE [pattern [pattern …]]:退订所有给定模式的频道。
5、SUBSCRIBE channel [channel …]:订阅给定的一个或多个频道的信息。
6、UNSUBSCRIBE [channel [channel …]]:指退订给定的频道。

实例

redis 127.0.0.1:6379> SUBSCRIBE redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1

先重新开启个 redis 客户端,然后在同一个频道 redisChat 发布两次消息,订阅者就能接收到消息。

redis 127.0.0.1:6379> PUBLISH redisChat "Redis is a great caching technique"
(integer) 1
redis 127.0.0.1:6379> PUBLISH redisChat "Learn redis by runoob.com"
(integer) 1

订阅者的客户端会显示如下消息

1) "message"
2) "redisChat"
3) "Redis is a great caching technique"
1) "message"
2) "redisChat"
3) "Learn redis by runoob.com"

注意:实际工作中不会用到redis的发布订阅,了解该功能就行。

配置文件redis.conf介绍

redis.conf 配置解析(设置红色的基本就可以自己用了,bind配置0.0.0.0后要在/etc/sysconfig/iptables配置相应的端口):
daemonize:如需要在后台运行,把该项的值改为yes
pdifile:把pid文件放在/var/run/redis.pid,可以配置到其他地址
bind:指定redis只接收来自该IP的请求,如果不设置,那么将处理所有请求,在生产环节中最好设置该项
(设置0.0.0.0 则改为用iptables来控制访问权限)
port:监听端口,默认为6379
timeout:设置客户端连接时的超时时间,单位为秒
loglevel:等级分为4级,debug,verbose,notice和warning。生产环境下一般开启notice,默认verbose
logfile:配置log文件名称
database:设置数据库的个数,默认使用的数据库是0,默认有16个数据库
save:设置redis进行数据库镜像的频率
stop-wirtes-on-bgsave-error:如果配置成no,表示你不在乎数据不一致或者有其他的手段发现和控制
rdbcompression:在进行镜像备份时,是否进行压缩(对于存储到磁盘中的快照,可以设置是否进行压缩,如果是,redis会采用LZF算法进行压缩,如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能)
rdbchecknum:在存储快照后,还可以让redis使用CRC64算法来进行数据校验,但这样会增加大约10%的性能消耗,如果希望取得最大性能特生,可以关闭此功能
dbfilename:镜像备份文件的文件名
dir:数据库镜像备份的文件放置的路径
slaveof:设置该数据库为其他数据库的从数据库
masterauth:当主数据库连接需要密码验证时,在这里设定
requirepass:设置客户端连接后进行任何其他指定前需要使用的密码
maxclients:限制同时连接的客户端数量
maxmemory:设置redis能够使用的最大内存
maxmemory-policy:缓存过期清洁策略
a、volatile-lru:使用LRU算法移除key,只对设置了过期时间的键
b、allkeys-lru:使用LRU算法移除key
c、volatile-random:在过期集合中移除随机的key,只对设置了过期的键;
d、allkeys-random:移除随机的key;
e、volatile-ttl:移除那些TTL值最小的key,即那些最近要过期的key;
f、noeviction:不进行移除。针对写操作,只是返回错误信息
maxmemory-samples:设置样本数量,LRU算法和最小TTL算法都并非是精确的算法,二室估算值,所以你可以设置样本的大小,redis默认会检查这么多个key并选择其中LRU的那个
appendonly:开启appendonly模式后,redis会把每一次所接收到的写操作都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态
appendfsync:设置appendonly.aof文件进行同步的频率
vm_enabled:是否开启虚拟内存支持
vm_swap_file:设置虚拟内存的交换文件的路径
vm_max_momery:设置开启虚拟内存后,redis将使用的最大物理内存的大小,默认为0
vm_page_size:设置虚拟内存页的大小
vm_pages:设置交换文件的总的page数量
vm_max_thrrads:设置vm IO同时使用的线程数量
SECURITY安全
1)获取密码命令:config get requirepass 默认为“”,即不要密码
2)设置密码命令:config set requirepass “123456”
3)输入密码:访问任何命令都需要输入密码,其格式为- auth 123456
Syslog-enabled:是否把日志输出到syslog中,默认no
Syslog-ident:指定syslog里的日志标识,默认redis
tcp-keepalive:单位为秒,如果设置为0,则不会进行Keepalive检测,建议设置成60
tcp-backlog:默认511。在高并发环境下需要一个高backlog值来避免慢客户端连接问题。注意Linux内核会将这个值减少到/proc/sys/net/core/somaxconn的值,所以需要确认增大somaxconn和tcp_max_syn_backlog两个值来达到想要的效果
Units单位:1)配置大小单位,开头定义了一些基本的度量单位,只支持bytes,不支持bit ;2)对大小写不敏感。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值