Redis学习与总结

Redis将按照以下的的顺序进行总结

  • Redis
  • Redis的常用命令
  • Redis的安装过程
  • Redis主从复制原理
  • Redis持久化原理
  • Redis的哨兵Sentinel机制
  • Redis的API使用

Redis

Redis 是一个开源、支持网络、基于内存、键值对的NoSQL数据库

Redis常用命令


Redis 支持string list hash set sortset 五种数据类型

http://8d9901d5.wiz01.com/share/s/2dCg7l3-1kCv2lEZIt2_gYod0iaUd42pBATf28cVd41LwKTl


Redis安装过程

安装环境:Linux centos
安装版本:redis-3.0.7
安装过程:
  • 下载 redis-3.0.7.tar.gz 并解压
  • 进入解压目录并make,然后可以看到src目录下的可执行命令
  • redis安装采用主从模式,使用redis的两种持久化方法:快照(RDB文件)与追加式文件(AOF文件);同时采用redis自带哨兵机制以完成主从切换。
  • 大部分的配置默认即可,下面为改动或者添加的部分
  •  下面是redis.conf中对应改动的部分
  1. #默认采用daemon的方式
  2. daemonize yes
  3. #改变默认的6379端口,防止人为攻击
  4. port 16379
  5. #指定redis的日志文件位置
  6. logfile /home/stat/redis-3.0.7/logs/redis.log
  7. #指定持久化文件的日志文件
  8. dir /home/stat/redis-3.0.7/data
  9. #这个只在slave侧的redis.conf中进行设置
  10. slaveof 10.186.150.201 16379
  11. #开启aof持久化方式
  12. appendonly yes
  •     下面是sentinel.conf中对应改动的部分
  1. #指定sentinel的工作目录
  2. dir "/home/stat/redis-3.0.7/data"
  3. #指定sentinel监控的master节点及端口
  4. sentinel monitor mymaster 10.186.150.201 16379 2
  • redis启动:./redis-server ../redis.conf
  • redis停止:./redis-cli -p 16379 shutdown
  • 其他的查询命令:
    • ./redis-cli -h host_ip -p 16379 (redis服务端口);INFO命令查看当前主机是slave还是master及其他状态
    • ./redis-cli -h host_ip -p 26379(redis sentinel服务端口);INFO  sentinel 查看sentinel哨兵信息;sentinel masters 查看master 节点信息;sentinel slaves mymaster(sentinel.conf制定的名字) 查看slave信息

Redis主从复制原理

  1. 配置好slave后,slave与master建立连接,然后发送sync命令. 
  2. 无论是第一次连接还是重新连接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存. 
  3. 后台进程完成写文件后,master就发送文件给slave,slave将文件保存到硬盘上,再加载到内存中, 
  4. 接着master就会把缓存的命令转发给slave,后续master将收到的写命令发送给slave. 
  5. 如果master同时收到多个slave发来的同步连接命令,master只会启动一个进程来写数据库镜像, 然后发送给所有的slave

Redis持久化原理

Redis有两种持久化的方式:快照(RDB文件)和追加式文件(AOF文件):

  • RDB持久化方式会在一个特定的间隔保存那个时间点的一个数据快照。
  • AOF持久化方式则会记录每一个服务器收到的写操作。在服务启动时,这些记录的操作会逐条执行从而重建出原来的数据。写操作命令记录的格式跟Redis协议一致,以追加的方式进行保存。
  • Redis的持久化是可以禁用的,就是说你可以让数据的生命周期只存在于服务器的运行时间里。
  • 两种方式的持久化是可以同时存在的,但是当Redis重启时,AOF文件会被优先用于重建数据。
RDB

工作原理
  • Redis调用fork(),产生一个子进程。
  • 子进程把数据写到一个临时的RDB文件。
  • 当子进程写完新的RDB文件后,把旧的RDB文件替换掉。
优点
  • RDB文件是一个很简洁的单文件,它保存了某个时间点的Redis数据,很适合用于做备份。你可以设定一个时间点对RDB文件进行归档,这样就能在需要的时候很轻易的把数据恢复到不同的版本。
  • 基于上面所描述的特性,RDB很适合用于灾备。单文件很方便就能传输到远程的服务器上。
  • RDB的性能很好,需要进行持久化时,主进程会fork一个子进程出来,然后把持久化的工作交给子进程,自己不会有相关的I/O操作。
  • 比起AOF,在数据量比较大的情况下,RDB的启动速度更快。
缺点
  • RDB容易造成数据的丢失。假设每5分钟保存一次快照,如果Redis因为某些原因不能正常工作,那么从上次产生快照到Redis出现问题这段时间的数据就会丢失了。
  • RDB使用fork()产生子进程进行数据的持久化,如果数据比较大的话可能就会花费点时间,造成Redis停止服务几毫秒。如果数据量很大且CPU性能不是很好的时候,停止服务的时间甚至会到1秒。
保存点(RDB的启用和禁用)

你可以配置保存点,使Redis如果在每N秒后数据发生了M次改变就保存快照文件。例如下面这个保存点配置表示每60秒,如果数据发生了1000次以上的变动,Redis就会自动保存快照文件:

save 60 1000

保存点可以设置多个,Redis的配置文件就默认设置了3个保存点:

# 格式为:save <seconds> <changes># 可以设置多个。
save 900 1 #900秒后至少1个key有变动
save 300 10 #300秒后至少10个key有变动
save 60 10000 #60秒后至少10000个key有变动

如果想禁用快照保存的功能,可以通过注释掉所有"save"配置达到,或者在最后一条"save"配置后添加如下的配置:

save ""

错误处理

默认情况下,如果Redis在后台生成快照的时候失败,那么就会停止接收数据,目的是让用户能知道数据没有持久化成功。但是如果你有其他的方式可以监控到Redis及其持久化的状态,那么可以把这个功能禁止掉。

stop-writes-on-bgsave-error yes

数据压缩

默认Redis会采用LZF对数据进行压缩。如果你想节省点CPU的性能,你可以把压缩功能禁用掉,但是数据集就会比没压缩的时候要打。

rdbcompression yes

数据校验

从版本5的RDB的开始,一个CRC64的校验码会放在文件的末尾。这样更能保证文件的完整性,但是在保存或者加载文件时会损失一定的性能(大概10%)。如果想追求更高的性能,可以把它禁用掉,这样文件在写入校验码时会用0替代,加载的时候看到0就会直接跳过校验。

rdbchecksum yes

手动生成快照

Redis提供了两个命令用于手动生成快照。

SAVE

SAVE命令会使用同步的方式生成RDB快照文件,这意味着在这个过程中会阻塞所有其他客户端的请求。因此不建议在生产环境使用这个命令,除非因为某种原因需要去阻止Redis使用子进程进行后台生成快照(例如调用fork(2)出错)。

BGSAVE

BGSAVE命令使用后台的方式保存RDB文件,调用此命令后,会立刻返回OK返回码。Redis会产生一个子进程进行处理并立刻恢复对客户端的服务。在客户端我们可以使用LASTSAVE命令查看操作是否成功。

127.0.0.1:6379> BGSAVEBackground saving started
127.0.0.1:6379> LASTSAVE
(integer) 1433936394

配置文件里禁用了快照生成功能不影响SAVEBGSAVE命令的效果。

AOF

快照并不是很可靠。如果你的电脑突然宕机了,或者电源断了,又或者不小心杀掉了进程,那么最新的数据就会丢失。而AOF文件则提供了一种更为可靠的持久化方式。每当Redis接受到会修改数据集的命令时,就会把命令追加到AOF文件里,当你重启Redis时,AOF里的命令会被重新执行一次,重建数据。

优点

  • 比RDB可靠。你可以制定不同的fsync策略:不进行fsync、每秒fsync一次和每次查询进行fsync。默认是每秒fsync一次。这意味着你最多丢失一秒钟的数据。
  • AOF日志文件是一个纯追加的文件。就算是遇到突然停电的情况,也不会出现日志的定位或者损坏问题。甚至如果因为某些原因(例如磁盘满了)命令只写了一半到日志文件里,我们也可以用redis-check-aof这个工具很简单的进行修复。
  • 当AOF文件太大时,Redis会自动在后台进行重写。重写很安全,因为重写是在一个新的文件上进行,同时Redis会继续往旧的文件追加数据。新文件上会写入能重建当前数据集的最小操作命令的集合。当新文件重写完,Redis会把新旧文件进行切换,然后开始把数据写到新文件上。
  • AOF把操作命令以简单易懂的格式一条接一条的保存在文件里,很容易导出来用于恢复数据。例如我们不小心FLUSHALL命令把所有数据刷掉了,只要文件没有被重写,我们可以把服务停掉,把最后那条命令删掉,然后重启服务,这样就能把被刷掉的数据恢复回来。

缺点

  • 在相同的数据集下,AOF文件的大小一般会比RDB文件大。
  • 在某些fsync策略下,AOF的速度会比RDB慢。通常fsync设置为每秒一次就能获得比较高的性能,而在禁止fsync的情况下速度可以达到RDB的水平。
  • 在过去曾经发现一些很罕见的BUG导致使用AOF重建的数据跟原数据不一致的问题。

启用AOF

把配置项appendonly设为yes

appendonly yes

文件路径和名称

# 文件存放目录,与RDB共用。默认为当前工作目录。dir ./

# 默认文件名为appendonly.aof
appendfilename "appendonly.aof"

可靠性

你可以配置Redis调用fsync的频率,有三个选项:

  • 每当有新命令追加到AOF的时候调用fsync。速度最慢,但是最安全。
  • 每秒fsync一次。速度快(2.4版本跟快照方式速度差不多),安全性不错(最多丢失1秒的数据)。
  • 从不fsync,交由系统去处理。这个方式速度最快,但是安全性一般。

推荐使用每秒fsync一次的方式(默认的方式),因为它速度快,安全性也不错。相关配置如下:

# appendfsync alwaysappendfsync everysec
# appendfsync no

日志重写(Rewrite机制)

随着写操作的不断增加,AOF文件会越来越大。例如你递增一个计数器100次,那么最终结果就是数据集里的计数器的值为最终的递增结果,但是AOF文件里却会把这100次操作完整的记录下来。而事实上要恢复这个记录,只需要1个命令就行了,也就是说AOF文件里那100条命令其实可以精简为1条。所以Redis支持这样一个功能:在不中断服务的情况下在后台重建AOF文件。

工作原理如下:

  • Redis调用fork(),产生一个子进程。
  • 子进程把新的AOF写到一个临时文件里。
  • 主进程持续把新的变动写到内存里的buffer,同时也会把这些新的变动写到旧的AOF里,这样即使重写失败也能保证数据的安全。
  • 当子进程完成文件的重写后,主进程会获得一个信号,然后把内存里的buffer追加到子进程生成的那个新AOF里。
  • Redis

我们可以通过配置设置日志重写的条件:

# Redis会记住自从上一次重写后AOF文件的大小(如果自Redis启动后还没重写过,则记住启动时使用的AOF文件的大小)。# 如果当前的文件大小比起记住的那个大小超过指定的百分比,则会触发重写。# 同时需要设置一个文件大小最小值,只有大于这个值文件才会重写,以防文件很小,但是已经达到百分比的情况。
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

要禁用自动的日志重写功能,我们可以把百分比设置为0:

auto-aof-rewrite-percentage 0

Redis 2.4以上才可以自动进行日志重写,之前的版本需要手动运行BGREWRITEAOF这个命令。

Redis数据恢复顺序


当redis服务器挂掉时,重启时将按以下优先级恢复数据到内存种:

1. 如果只配置了AOF,重启时加载AOF文件恢复数据.

2. 如果同时配置了RBD和AOF,启动时只加载AOF文件恢复数据.

3. 如果只配置了㻾DB,启动时将加载dump文件恢复数据.

数据损坏修复

如果因为某些原因(例如服务器崩溃)AOF文件损坏了,导致Redis加载不了,可以通过以下方式进行修复:

  • 备份AOF文件。
  • 使用redis-check-aof命令修复原始的AOF文件:

    $ redis-check-aof --fix
  • 可以使用diff -u命令看下两个文件的差异。
  • 使用修复过的文件重启Redis服务。

从RDB切换到AOF

这里只说Redis >= 2.2版本的方式:

  • 备份一个最新的dump.rdb的文件,并把备份文件放在一个安全的地方。
  • 运行以下两条命令:

    $ redis-cli config set appendonly yes
    $ redis-cli config set save ""
  • 确保数据跟切换前一致。

  • 确保数据正确的写到AOF文件里。

第二条命令是用来禁用RDB的持久化方式,但是这不是必须的,因为你可以同时启用两种持久化方式。

记得对配置文件redis.conf进行编辑启用AOF,因为命令行方式修改配置在重启Redis后就会失效。

备份

建议的备份方法

  • 创建一个定时任务,每小时和每天创建一个快照,保存在不同的文件夹里。
  • 定时任务运行时,把太旧的文件进行删除。例如只保留48小时的按小时创建的快照和一到两个月的按天创建的快照。
  • 每天确保一次把快照文件传输到数据中心外的地方进行保存,至少不能保存在Redis服务所在的服务器
Redis哨兵机制

Sentinel(哨兵)是用于监控redis集群中Master状态的工具


Sentinel作用


  1. Master状态检测
  2. 如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Master作为Slave
  3. Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换

Sentinel工作方式


  1. 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令
  2. 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线
  3. 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态
  4. 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线
  5. 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令
  6. 当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次
  7. 若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的主观下线状态就会被移除
  8. 若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除


备注

主观下线:Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个redis服务器做出的下线判断

客观下线:Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,然后开启failover.

SDOWN适合于Master和Slave,只要一个 Sentinel 发现Master进入了ODOWN, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对下线的主服务器执行自动故障迁移操作。

ODOWN只适用于Master,对于Slave的 Redis 实例,Sentinel 在将它们判断为下线前不需要进行协商, 所以Slave的 Sentinel 永远不会达到ODOWN。

注意点

  1. 首次启动时,必须先启动Master
  2. Sentinel 只在 server 端做主从切换,app端要自己开发(例如Jedis库的SentinelJedis,能够监控Sentinel的状态)
  3. 若Master已经被判定为下线,Sentinel已经选择了新的Master,也已经将old Master改成Slave,但是还没有将其改成new Master。若此时重启old Master,则Redis集群将处于无Master状态,此时只能手动修改配置文件,然后重新启动集群

Redis API使用

Redis的使用需要用到API,maven依赖如下
     
     
  1. <dependency>
  2. <groupId>redis.clients</groupId>
  3. <artifactId>jedis</artifactId>
  4. <version>2.7.3</version>
  5. </dependency>
Redis的使用主要以下三种:
  • 直接使用Redis的接口Jedis
  • 使用Redis资源池的接口JedisPool
    • 资源池维护一个资源连接池,jedis实例可以动态的从中获取连接资源
  • 使用Redis 集群的接口JedisCluster
    • JedisCluster是jedis封装的关于redis cluster操作的class;
    • JedisCluster里主要有两个成员变量:maxRedirections和connectionHandler
    • JedisCluster会从connectionHandler基于key找出对应的SLOTS和NODES,并找出对应的JedisPool对象
    • 从JedisPool对象中找出可用的Jedis实例,执行Jedis的对应操作

JedisPool的使用
JedisPool的配置
     
     
  1. JedisPoolConfig config = new JedisPoolConfig();
  2. String host = Config.getM_strRedisIp();
  3. int port = Config.getM_nRedisPort();
  4. config.setMaxTotal(MAX_ACTIVE);
  5. config.setMaxIdle(MAX_IDLE);
  6. config.setMaxWaitMillis(MAX_WAIT);
  7. config.setTestOnBorrow(TEST_ON_BORROW);
  8. jedisPool = new JedisPool(config, host, port, TIMEOUT);
JedisPool之Jedis实例调用
     
     
  1. Jedis jedis = jedisPool.getResource();

JedisCluster的使用
    
    
  1. #设置集群的节点
  2. Set<HostAndPort> nodes = new HashSet<HostAndPort>();
  3. String redisCluster = Config.getM_strRedisCluster();
  4. String[] ipPorts = redisCluster.split(",");
  5. for (String ipPort : ipPorts)
  6. {
  7. String ip = ipPort.split(":")[0];
  8. String port = ipPort.split(":")[1];
  9. nodes.add(new HostAndPort(ip, Integer.parseInt(port)));
  10. }
  11. #配置config
  12. JedisPoolConfig poolConfig = new JedisPoolConfig();
  13. poolConfig.setMaxIdle(5);
  14. poolConfig.setMaxTotal(20);
  15. // 在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
  16. poolConfig.setTestOnBorrow(true);
  17. #设置超时时间
  18. int timeout = 5000;
  19. #创建jedisCluster
  20. JedisCluster jedisCluster = new JedisCluster(nodes, timeout, poolConfig);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值