一、redis的持久化
Snapshotting快照持久化(RDB)
快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。可以通过配置设置自动做快照持久化的方式。我们可以配置redis在n秒内如果超过m个key被修改就自动做快照,下面是默认的快照保存配置:
save 900 1 #900秒内如果超过1个key被修改,则发起快照保存
save 300 10 #300秒内容如超过10个key被修改,则发起快照保存
save 60 10000
client 也可以使用save或者bgsave命令通知redis做一次快照持久化,每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步脏数据。如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能。另外由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。
Append-only(AOF)
redis会将每一个收到的写命令都通过write函数追加到文件中(默认是appendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
appendonly yes #启用aof持久化方式
# appendfsync always #每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐(没有最好,只有更合适。。。)
# appendfsync no #完全依赖os,性能最好,持久化没保证
二、redis主从
redis主从复制过程: 当配置好slave后,slave与master建立连接,然后发送sync命令。无论是第一次连接还是重新连接,master都会启动一个后台进程,将 数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存。后台进程完成写文件后,master就发送文件给slave,slave将 文件保存到硬盘上,再加载到内存中,接着master就会把缓存的命令转发给slave,后续master将收到的写命令发送给slave。如果master同时收到多个slave发来的同步连接命令,master只会启动一个进程来写数据库镜像,然后发送给所有的slave。master同步数据时是非阻塞式的,可以接收用户的读写请求。然而在slave端是阻塞模式的,slave在同步master数据时,并不能够响应客户端的查询。
操作:
新建一个master-slave文件夹,在文件夹下新建master和slave两个文件夹,将原有的redis.conf文件分别复制到两个文件夹中,修改port(用不同的端口号模拟两个服务器)、redis.pid、redis.log,分别启动这个redis服务,连接一个reids服务,info命令,查看
可以观察到,连个服务的role都是master。
目标:将3000端口服务作为2000端口服务的从
1、命令方式:
连接3000端口的服务,slaveof 192.168.188.128 2000
然后info,会观察到role变成了slave,并且连接2000端口的服务,info,会看到该端口下的slave的ip和port信息。
缺点:重启服务,该master,slave关系会消失。。。。。
2、通过配置文件:
通过配置文件redis.conf文件的方式实现主从关系(可以实现关系的永久性)
slaveof 192.168.188.129 2000(将当前服务的主服务设置为192.168.188.129下的端口为2000的服务)
在master服务中,set name bao,切换slave服务 get name,控制台会打印出bao......
master服务器可读可写,但是slave服务器却只能读。。。主从的作用:通过读写分离,减轻master服务器的压力。。。。。。
master-slave环境搭建完成。。。。。。
三、Redis集群
Redis 集群中内置了 16384 个哈希槽(hashslots),当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。集群的每个节点负责一部分hash槽。这种结构很容易添加或者删除节点,并且无论是添加删除或者修改某一个节点,都不会造成集群不可用的状态。使用哈希槽的好处就在于可以方便的添加或移除节点。当需要增加节点时,只需要把其他节点的某些哈希槽挪到新节点就可以了;当需要移除节点时,只需要把移除节点上的哈希槽挪到其他节点就行了;在这一点上,我们以后新增或移除节点的时候不用先停掉所有的 redis 服务。
redis集群原理和hashmap的原理相似,感兴趣的同学可以研究下hashmap的存储结构。。。。。
基于centos的集群
1、集群至少要有3个节点(一主一从),每个节点都有主从结构
新建六个文件夹,把配置文件cp进去,然后修改配置文件端口,把支持集群配置放开,启动该节点
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
2、安装ruby,必须2.0以上,2.0以上自带rubygems包管理器
yum install ruby
3、gem命令安装redis包,增加redis-trib.rb调用redis的接口包
gem install redis
安装成功后,通过gem list命令查看是否包含redis包
4、用redis-trib.rb集群工具管理redis集群
./redis-trib.rb create --replicas 1(表示1个主服务下有一个从服务) 120.77.22.187:1000 120.77.22.187:2000 120.77.22.187:3000 120.77.22.187:1010 120.77.22.187:2010 120.77.22.187:3010
5、连接redis集群:
redis-cli -c -h 192.168.188.128 -p 1000(无论连接集群中的哪个服务,都是连接上了集群)
cluster info:看到集群的状态:OK
cluster nodes:查看redis集群的关系
四、redis集群添加节点
通过前面所说的,redis集群是通过18364个hash槽对键值进行匹配存储的,因此如果要增加redis集群节点,必须给新增的节点分配一部hash槽,这样数据才有可能会存储到新增的节点上。
新增集群节点:
新建两个文件夹:4000、4010,分别向这两个文件夹中cp redis.conf文件,修改port分别为
4000、4010,修改pid和log地址。
在src文件夹中,通过redis-trib.rb命令进行添加master节点。
./redis-trib.rb add-node 192.168.188.128:4000 192.168.188.128:1000(将4000对应的节点加到1000对应的集群中)
连接4000这个端口的redis服务,通过cluster nodes命令进行查看集群中的nodes信息,可以看到nodes的role和hash槽点信息。可以看到新增加的节点并没有分配hash槽。下面要手动分配:
手动配置hashslots:
./redis-trib.rb reshard 192.168.188.128:1000(这个ip和port是集群中的任意一个)
(1)首先会询问要分配多少hash槽点给新的node
(2)接着询问是哪个节点的ID接受这些hash槽(这里是新增的4000这个节点的ID)
(3)询问这些hash槽从哪来:
a、“all”:从集群中的所有master节点的hash槽中抽取出来。
b、“done”:从一个存在hash槽的master节点中抽取。。。。
一般我选择all
(4)yes
重新查看cluster nodes,可以查看新增的node节点有了新的hash槽。。。。
为新增的master节点添加slave节点:
首先将4010节点添加到集群中,并通过cluster replicate (要加入master的id)命令将4010作为slave节点加入到4000节点上。
删除节点:
如果删除的slave节点,直接通过./redis-trib.rb del-node (ip:端口 要删除的slave的id)
删除master节点:
在删除master服务时,要将master的hash槽分配到其他节点上。
将要删除的节点的hash槽分配到其他节点中
./redis-trib.rb reshard 192.168.188.128:4000
分1000个槽点
分到2000的id上
源头是4000的id
done
删除该节点:
./redis-trib.rb del-node 192.168.188.128:4000 (master的id)
五、Redis-sentinel高可用
Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换。
它的功能有以下几点:
1、不时地监控redis是否按照预期良好地运行;
2、如果发现某个redis节点运行出现状况,能够通知另外一个进程(例如它的客户端);
3、能够进行自动切换。当一个master节点不可用时,能够选举出master的多个slave(如果有超过一个slave的话)中的一个来作为新的master,其它的slave节点会将它所追随的master的地址改为被提升为master的slave的新地址。
4、需要注意的是,配置文件在sentinel运行期间是会被动态修改的,例如当发生主备切换时候,配置文件中的master会被修改为另外一个slave。这样,之后sentinel如果重启时,就可以根据这个配置来恢复其之前所监控的redis集群的状态。
操作:
修改sentinel.conf文件:
sentinel monitor mymaster 127.0.0.1 6379 1
sentinel down-after-milliseconds mymaster 60000
#sentinel can-failover mymaster yes
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
当sentinel集群式,解决这个问题的方法就变得很简单,只需要多个sentinel互相沟通来确认某个master是否真的死了,这个2代表,当集群中有2个sentinel认为master死了时,才能真正认为该master已经不可用了。
down-after-milliseconds
sentinel会向master发送心跳PING来确认master是否存活,如果master在“一定时间范围”内不回应PONG 或者是回复了一个错误消息,那么这个sentinel会主观地(单方面地)认为这个master已经不可用了(subjectively down, 也简称为SDOWN)。而这个down-after-milliseconds就是用来指定这个“一定时间范围”的,单位是毫秒。
can-failover
no 表示当前sentinel是一个观察者,只参与投票不参与实施failover
全局中至少有一个是yes
parallel-syncs
当新master产生时,同时进行“slaveof”到新master并进行“SYNC”的slave个数
默认为1,建议保持默认值
在salve执行salveof与同步时,将会终止客户端请求
failover-timeout
failover过期时间,当failover开始后,在此时间内仍然没有触发任何failover操作
当前sentinel将会认为此次failoer失败
启动哨兵机制:
方式一:./redis-sentinel ../sentinel.conf
方式二:redis-server /path/to/sentinel.conf --sentinel
测试:手动停止某个节点的master服务,然后连接集群,通过cluster nodes查看节点状态,发现停止的那个master不可到达(表示已经中断),而该节点的某个slave节点会变成master节点。再将原来的master服务重启,再查看各节点状态,发现原来停止的master变成了slave。这就表明哨兵机制完成了主从切换的功能。