1 前提环境
虚拟机 redis 版本 5.3 准备三台服务
192.168.2.130
192.168.2.129
192.168.2.128
2 、Redis 安装部署
官网下载地址:https://redis.io/download,这里我们下载目前最新版5.0.7,
或者直接使用命令下载
wget http://download.redis.io/releases/redis-5.0.7.tar.gz
安装部署就不介绍了 启动单个测试 启动命令
/usr/local/redis-5.0.7/bin ./redis-server /usr/local/redis-5.0.7/redis.conf
启动后查看redis的进程,如下,可以看到6379端口就是我们运行的 redis 服务
redis-cli -p 6379 shutdown
3 Redis 集群整体架构**
这里我们采用的集群整体架构就是主从结构+哨兵(sentinel),实现容灾的自动切换
redis架构(主从+哨兵)
一个主节点(master)可拥有多个从节点(slave),从节点实现对主节点的复制,保证数据同步。而哨兵(sentinel)则对各节点进行监控,主要包括主节点存活检测、主从运行情况检测等,一旦主节点宕机,哨兵可自动进行故障转移
(failover)、主从切换。接下来就开始搭建这样一个集群,首先是主从结构,然后是哨兵模式
4 Redis 主从配置及数据同步
在第一步 Redis 安装部署中我们已经启动了 Redis 服务,但是配置文件并没有做修改,因为主从配置主要就是通过修改配置文件来实现,所以
Redis 配置文件的修改统一在这里进行讲解。 这里我创建了三台虚拟机来演示,分别按照上述安装方式安装好 Redis,三台虚拟机如下配置:
IP地址端口号角色 192.168.2.128 6379主机(master)
192.168.2.129 6379 从机(slave)
192.168.2.130 6379从机(slave)
下redis.conf 配置文件中的各个参数
1. # redis进程是否以守护进程的方式运行,yes为是,**no**为否(不以守护进程的方式运行会占用一个终端)。
2. daemonize **no**
3. # 指定redis进程的PID文件存放位置
4. pidfile /var/run/redis.pid
5. # redis进程的端口号
6. port 6379
7. #是否开启保护模式,默认开启。要是配置里没有指定bind和密码。开启该参数后,redis只会本地进行访问,拒绝外部访问。要是开启了密码和bind,可以开启。否则最好关闭设置为**no**。
8. protected-mode yes
9. # 绑定的主机地址
10. bind 127.0.0.1
11. # 客户端闲置多长时间后关闭连接,默认此参数为0即关闭此功能
12. timeout 300
13. # redis日志级别,可用的级别有debug.verbose.notice.warning
14. loglevel verbose
15. # log文件输出位置,如果进程以守护进程的方式运行,此处又将输出文件设置为stdout的话,就会将日志信息输出到/dev/null里面去了
16. logfile stdout
17. # 设置数据库的数量,默认为0可以使用**select** <dbid>命令在连接上指定数据库id
18. databases 16
19. # 指定在多少时间内刷新次数达到多少的时候会将数据同步到数据文件
20. save <seconds> <changes>
21. # 指定存储至本地数据库时是否压缩文件,默认为yes即启用存储
22. rdbcompression yes
23. # 指定本地数据库文件名
24. dbfilename dump.db
25. # 指定本地数据问就按存放位置
26. dir ./
27. # 指定当本机为slave服务时,设置master服务的IP地址及端口,在redis启动的时候他会自动跟master进行数据同步
28. replicaof <masterip> <masterport>
29. # 当master设置了密码保护时,slave服务连接master的密码
30. masterauth <master-**password**>
31. # 设置redis连接密码,如果配置了连接密码,客户端在连接redis是需要通过AUTH<**password**>命令提供密码,默认关闭
32. requirepass footbared
33. # 设置同一时间最大客户连接数,默认无限制。redis可以同时连接的客户端数为redis程序可以打开的最大文件描述符,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回 **max** number **of** clients reached 错误信息
34. maxclients 128
35. # 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的**Key**。当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把**Key**存放内存,Value会存放在swap区
36. maxmemory<bytes>
37. # 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为**no**。
38. appendonly **no**
39. # 指定跟新日志文件名默认为appendonly.aof
40. appendfilename appendonly.aof
41. # 指定更新日志的条件,有三个可选参数 - **no**:表示等操作系统进行数据缓存同步到磁盘(快),always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全), everysec:表示每秒同步一次(折衷,默认值);
42. appendfsync everysec
主机配置 192.168.2.128
1. bind:0.0.0.0 注释掉
2. port:6379
3. protected-mode:**no** 关闭保护模式,可以外部访问。
4. daemonize:yes 设置为后台启动。
5. logfile:./redis.log 日志文件位置(/usr/local/redis/redis.log)
6. requirepass:密码 设置 redis 连接密码
7. masterauth:密码 slave 服务连接 master 的密码
Redis 默认只允许本机访问,把 bind 修改为 0.0.0.0 表示允许所有远程访问。如果想指定限制访问,可设置对应的 ip。
**从机配置 192.168.2.129**
1. bind:0.0.0.0
2. port:6379
3. protected-mode:**no**
4. daemonize:yes
5. logfile:./redis.log
6. requirepass:password
7. masterauth:password
8. replicaof 192.168.2.128 6379
replicaof 192.168.2.128 6379 指定当本机为 slave 服务时,设置 master 服务的IP地址及端口,在 redis 启动的时候会自动跟 master 进行数据同步,所以两台从机都这样配置即可
注:由于我们搭建的集群需要自动容灾切换,主数据库可能会变成从数据库,所以三台机器上都需要同时设置 requirepass 和 masterauth 配置项。
主从验证
进入redis 客户端 执行命令
INFO replication
查询集群状态
127.0.0.1:6379[1]> info replication
role:slave (从机)
master_host:192.168.2.130
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:1266695
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:21a0deb62cc4a6142e5efa71a045f521c3aa1376
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1266695
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:218120
repl_backlog_histlen:1048576
Redis 哨兵模式搭建**
哨兵的配置主要就是修改sentinel.conf
配置文件中的参数
1. # 哨兵sentinel实例运行的端口,默认26379
2. port 26379
3. # 哨兵sentinel的工作目录
4. dir ./
5. # 是否开启保护模式,默认开启。
6. protected-mode:**no**
7. # 是否设置为后台启动。
8. daemonize:yes
9.
10. # 哨兵sentinel的日志文件
11. logfile:./sentinel.log
12.
13. # 哨兵sentinel监控的redis主节点的
14. # ip:主机ip地址
15. # port:哨兵端口号
16. # master-**name**:可以自己命名的主节点名字(只能由字母A-z、数字0-9 、这三个字符".-_"组成。)
17. # quorum:当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
18. # sentinel monitor <master-**name**> <ip> <redis-port> <quorum>
19. sentinel monitor mymaster 127.0.0.1 6379 2
20.
21. # 当在Redis实例中开启了requirepass,所有连接Redis实例的客户端都要提供密码。
22. # sentinel auth-pass <master-**name**> <**password**>
23. sentinel auth-pass mymaster password
24.
25. # 指定主节点应答哨兵sentinel的最大时间间隔,超过这个时间,哨兵主观上认为主节点下线,默认30秒
26. # sentinel down-**after**-milliseconds <master-**name**> <milliseconds>
27. sentinel down-**after**-milliseconds mymaster 30000
28.
29. # 指定了在发生failover主备切换时,最多可以有多少个slave同时对新的master进行同步。这个数字越小,完成failover所需的时间就越长;反之,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。可以通过将这个值设为1,来保证每次只有一个slave,处于不能处理命令请求的状态。
30. # sentinel parallel-syncs <master-**name**> <numslaves>
31. sentinel parallel-syncs mymaster 1
32.
33. # 故障转移的超时时间failover-timeout,默认三分钟,可以用在以下这些方面:
34. # 1. 同一个sentinel对同一个master两次failover之间的间隔时间。
35. # 2. 当一个slave从一个错误的master那里同步数据时开始,直到slave被纠正为从正确的master那里同步数据时结束。
36. # 3. 当想要取消一个正在进行的failover时所需要的时间。
37. # 4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来同步数据了
38. # sentinel failover-timeout <master-**name**> <milliseconds>
39. sentinel failover-timeout mymaster 180000
40.
41. # 当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本。一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
42. # 对于脚本的运行结果有以下规则:
43. # 1. 若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10。
44. # 2. 若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
45. # 3. 如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
46. # sentinel notification-script <master-**name**> <script-path>
47. sentinel notification-script mymaster /var/redis/notify.sh 49. # 这个脚本应该是通用的,能被多次调用,不是针对性的。
50. sentinel client-reconfig-script <master-**name**> <script-path>
52. sentinel client-reconfig-script mymaster
53. /var/redis/reconfig.sh
部署三个哨兵,每台服务器一个哨兵,配置方式相同
1. #端口默认为26379。
2. port:26379
3. #关闭保护模式,可以外部访问。
4. protected-mode:**no**
5. #设置为后台启动。
6. daemonize:yes
7. #日志文件。
8. logfile:./sentinel.log
9. #指定主机IP地址和端口,并且指定当有2台哨兵认为主机挂了,则对主机进行容灾切换。
10. sentinel monitor mymaster 192.168.2.128 6379 2
11. #当在Redis实例中开启了requirepass,这里就需要提供密码。
12. sentinel auth-pass mymaster pwdtest@2019 你的密码
13. #这里设置了主机多少秒无响应,则认为挂了。
14. sentinel down-**after**-milliseconds mymaster 3000
15. #主备切换时,最多有多少个slave同时对新的master进行同步,这里设置为默认的1。
16. snetinel parallel-syncs mymaster 1
17. #故障转移的超时时间,这里设置为三分钟。
18. sentinel failover-timeout mymaster 180000
配置完成后依次启动
1. cd /data/redis-5.0.7/bin
2. redis-sentinel /use/local/redis/sentinel.conf
3 redis-cli -p 26379 进入客户端
4 info sentinel 查询哨兵状态
搭建完成 测试 停掉主机 是否进行主从修改
配置后 从服务是只读的无法进行写入的
springCloud 集合redis 集器哨兵配置
jar包引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
yml配置
redis:
sentinel:
master: mymaster
nodes: 192.168.2.128:26379,192.168.2.129:26379,192.168.2.130:26379
password: password
database: 1
lettuce:
pool:
max-idle: 8
min-idle: 1
max-active: 8
max-wait: -1
application.properties填写配置信息
####redis的配置信息###
spring.redis.sentinel.master=mymaster
spring.redis.sentinel.nodes=host1:port1,host2:port2,...
spring.redis.password=password......
采用哪个数据库
spring.redis.database=0
连接池最大连接数,默认8个,(使用负值表示没有限制)
spring.redis.pool.max-active=8
连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
连接池中的最大空闲连接
spring.redis.pool.max-idle=8
连接池中的最小空闲连接
spring.redis.pool.min-idle=0
连接超时时间(毫秒)
spring.redis.timeout=0
自定义redis序列化
@Configuration
@EnableCaching
public class RedisConfig {
@Autowired
private RedisTemplate<Object,Object> redisTemplate;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
/**
* 处理乱码
*
* @return
*/
@Bean
public RedisTemplate redisTemplateInit() {
// key序列化
redisTemplate.setKeySerializer(new StringRedisSerializer());
//val实例化
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer() {
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
return redisMessageListenerContainer;
}
}