环境描述:
主redis:192.168.10.1 6379
从redis:192.168.10.2 6380
一、主从配置
aemonize no 改为 yes
从redis配置文件redis.conf中的port 6379 改为 6380,添加slaveof 192.168.10.1 6379
3、启动主从服务
主redis:
[root@localhost redis-2.8.3]# src/redis-server /soft/redis-2.8.3-master/redis-2.8.3/redis.conf
从redis:
[root@localhost redis-2.8.3]# src/redis-server /soft/redis-2.8.3-slave/redis-2.8.3/redis.conf
4、测试数据同步
主redis:
src/redis-cli -p 6379
127.0.0.1:6379> set name abc
OK
127.0.0.1:6379> get name
"abc"
127.0.0.1:6379>
从redis:
src/redis-cli -p 6380
127.0.0.1:6380> get name
"abc"
127.0.0.1:6380>
5、默认是读写分离的
在从redis:
src/redis-cli -p 6380
127.0.0.1:6380> set name 123
(error) READONLY You can't write against a read only slave.
二、主从切换
1、停止主redis
src/redis-cli -n 6379 shutdown
src/redis-cli -p 6379
Could not connect to Redis at 127.0.0.1:6379: Connection refused
not connected>
2、将从redis设成主redis
src/redis-cli -p 6380 slaveof NO ONE
OK
3、测试从redis是否切换从主redis
src/redis-cli -p 6380
127.0.0.1:6380> set name 123
OK
127.0.0.1:6380> get name
"123"
127.0.0.1:6380>
4、原来的主redis恢复正常了,要重新切换回去
1)将现在的主redis的数据进行保存
src/redis-cli -p 6380
127.0.0.1:6380> get name
"abc"
127.0.0.1:6380> set name 123
OK
127.0.0.1:6380> get name
"123"
127.0.0.1:6380> save
OK
127.0.0.1:6380> get name
"123"
127.0.0.1:6380>
dump.rdb文件拷贝覆盖到原来主redis的根目录
3)启动原来的主redis
[root@localhost redis-2.8.3]# src/redis-server /soft/redis-2.8.3-master/redis-2.8.3/redis.conf
4)在现在的主redis中切换
src/redis-cli -p 6380 slaveof 192.168.10.1 6379
OK
当redis的master出现问题的时候,是否依然可以请求slave
slave-serve-stale-data yes
slave是否只读 slave-read-only yes slave每隔10s ping 一次master repl-ping-slave-period 10 slave的优先级,,master选举的依据 slave-priority 100 *redis.conf配置文件中配置 save "" 可以禁用rdb快照方式 , 但是在redis的客户端执行 save命令的话 , 依然会产生 rdb文件 *禁用了rdb快照方式以后 , redis的主从同步依然会产生rdb文件 *主从同步从库断开以后 , 重新建立主从同步 , 会从断开的offset开始同步 , *禁用rdb快照以后 , 只是会保证 , 没有 自动触发条件 产生rdb文件 redis高可用(sentinel)
cd /opt/redis320/config
touch sentinel.conf
vim sentinel.conf
sentinel monitor mymaster 192.168.10.160 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
#sentinel monitor resque 192.168.1.3 6380 4
#sentinel down-after-milliseconds resque 10000
#sentinel failover-timeout resque 180000
#sentinel parallel-syncs resque 5
启动sentinel :
redis-server /opt/redis320/config/sentinel.conf --sentinel
出现这样的提示表示 sentinel成功
1322:X 05 Jun 19:14:56.449 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1322:X 05 Jun 19:14:56.449 # Sentinel ID is 6927b6e2b5539dedb2fd040ced7a5bd6d1b52a77
1322:X 05 Jun 19:14:56.449 # +monitor master mymaster 192.168.10.160 6379 quorum 1
1322:X 05 Jun 19:14:56.452 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 192.168.10.160 6379
1322:X 05 Jun 19:15:56.454 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 192.168.10.160 6379
1322:X 05 Jun 19:16:03.166 # +sdown master mymaster 192.168.10.160 6379
1322:X 05 Jun 19:16:03.166 # +odown master mymaster 192.168.10.160 6379 #quorum 1/1
在运行sentinel的时候要注意:
*是否有密码配置 , 如果
被监控的master-slave是有密码设置的,需要在sentinel的配置文件中添加 sentinel auth-pass <master-name> <password> 配置
*关闭防火墙
我们配置两个sentinel进程:
vi sentinel.conf
port 26379
sentinel monitor mymaster 127.0.0.1 6000 2
<br>sentinel auth-pass mymaster 123456
vi sentinel.conf
port 26479
sentinel monitor mymaster 127.0.0.1 6000 2
sentinel auth-pass mymaster 123456
启动sentinel服务(到对应的目录执行相应的命令):
redis-server sentinel.conf --sentinel
查看日志:
[7014] 11 Jan 19:42:30.918 # +monitor master mymaster 127.0.0.1 6000 quorum 2
[7014] 11 Jan 19:42:30.923 * +slave slave 127.0.0.1:6002 127.0.0.1 6002 @ mymaster 127.0.0.1 6000
[7014] 11 Jan 19:42:30.925 * +slave slave 127.0.0.1:6001 127.0.0.1 6002 @ mymaster 127.0.0.1 6000
从对应的日志观察到,一个master服务,两个slave服务
我们现在来kill master进程
[root@localhost slave1]# ps -ef|grep redis
root 6960 1 0 19:29 ? 00:00:02 redis-server *:6000
root 6968 1 0 19:30 ? 00:00:01 redis-server *:6001
root 6975 1 0 19:30 ? 00:00:01 redis-server *:6002
root 7014 6570 0 19:42 pts/0 00:00:01 redis-server *:26479
root 7017 6789 0 19:42 pts/5 00:00:01 redis-server *:26379
root 7021 6729 0 19:46 pts/3 00:00:00 grep redis
[root@localhost slave1]# kill -9 6960
我们观察日志:
[7014] 11 Jan 19:43:41.463 # +sdown master mymaster 127.0.0.1 6000
[7014] 11 Jan 19:46:42.379 # +switch-master mymaster 127.0.0.1 6000 127.0.0.1 6001
master切换了,当6000端口的这个服务重启的时候,他会变成6001端口服务的slave。
因为sentinel在切换master的时候,把对应的sentinel.conf和redis.conf文件的配置修改。
期间我们还需要关注的一个问题:sentinel服务本身也不是万能的,也会宕机,所以我们还得部署sentinel集群,象我这样多启动几个sentinel。
关注这个配置:
sentinel monitor mymaster 127.0.0.1 6000 2<br><br><br>这个后面的数字2,是指当有两个及以上的sentinel服务检测到master宕机,才会去执行主从切换的功能。
redis持久化
Redis的持久化有两种 , RDB和AOF , 这两种方式都有他们的特点, 可以根据特点在不同的应用场景使用
RDB原理和场景:
说到rdb的原理,首先要说到这个的触发条件 , 一种是手动触发 , 一种是自动触发
自动触发 的条件是在 配置文件 中配置的 ,
save 900 1 #900s的时间内如果有一个key有变化,就会触发rdb
save 300 10 #300s的时间内如果有10个key有变化
save 60 10000 #60s的时间内如果有10000个key有变化
可以通过 save "" 来禁用
手动触发
是通过在客户端命令行执行 save 或者 bgsave 命令触发的
这两个命令的区别在于 是否会阻塞 当前的客户端请求,
save会阻塞客户端请求 , 而bgsave不会阻塞客户端请求,
save是占用当前的主进程将所有的redis数据快照到 rdb 文件中
bgsave是主进程fork一个子进程 , 然后通过 copy - on - write 来将数据快照到rdb文件中
但是bgsave有一个缺陷 ,
因为是使用的 copy - on - write 技术 , 所以 RDB模式需要Redis服务所占内存的1倍的内存 ,如果数据量太大而内存太小的话,
就会导致 数据不会完整的快照到rdb文件中 , 所以rdb技术只是适合备份 , 如果是需要可靠性的话,就需要 AOF 来支持了,下面会介绍 AOF技术
bgsave的工作流程:
Redis调用fork()。于是我们有了父子两个进程。
子进程开始将数据集写入一个临时RDB文件。
当子进程完成了新RDB文件,替换掉旧文件。
rdb除了备份以外 , 另一个重要的应用场景就是 主从同步 了
AOF的原理和场景:
aof的方式是类似于 mysql的binlog , 如果大家对于mysql比较熟悉的话,可能会理解的很快 , 和mysql 的binlog 的区别就是 ,
binlog是可以用于进行mysql主从同步的,
但是aof只是redis用于持久化的方式 .
aof的原理就是用户在客户端的操作命令都会记录到aof文件中 , 触发的条件在配置文件中进行配置 ,
appendonly yes //启用aof持久化方式
# appendfsync always //收到写命令就立即写入磁盘, 最慢 , 但是能够保证完全的持久化
appendfsync everysec //每分钟写入磁盘一次, 在性能和持久化之间做了很好的折中 (默认配置, 很好)
#appendfsync no //完全依赖os, 性能最好 , 持久化没有保证
aof主要用户对数据需要高可靠性的场景.
但是记录每次用户的操作记录 , 可能造成的后果是 出现很多的无用指令 , 就是可以被优化的 ,
所以 aof 又有着两个配置 ,对aof文件进行重写 ,
#当aof文件达到64m的时候,会自动 重写 aof文件 ,缩小文件大小
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
这段配置的意思是 当aof的文件到达 64m 的时候, 对aof文件进行重写 , 使得aof文件变得更小 , 以后每增长 100%(64m , 128m , 192m ... ) 的时候,都会触发这个优化动作;
但是aof的这个重写操作的原理是 rewrite会像replication一样,fork出一个子进程,创建一个临时文件,遍历数据库,将每个key、value对输出到临时文件。 也就是说 ,
还是 copy-on-write 的问题 ...