Docker_Redis
1. docker pull
拉取redis,并准备相对应版本的配置文件,配置文件不对应的话,可能会出问题。
[root@localhost redis]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis 4.0 8280a2c45ce5 3 weeks ago 89.2MB
2. 修改配置文件
- 主机配置文件(只列出修改部分)
# bind 127.0.0.1 # 注掉ip绑定
protected-mode yes # 打开保护模式
port 6379 # 主机默认6379
masterauth 123456 # 从机也有密码,加上验证
requirepass 123456 # 验证密码
- 从机1配置文件(只列出修改部分)
# bind 127.0.0.1 # 注掉ip绑定
protected-mode yes # 打开保护模式
port 6380 # 从机6380端口
slaveof 192.168.0.159 6379 # 加上主机的ip和端口,等会儿docker启动redis的时候,使用的network是host,所以ip可以确定
masterauth 123456 # 从机也有密码,加上验证
requirepass 123456 # 验证密码
- 从机2配置文件(只列出修改部分)
# bind 127.0.0.1 # 注掉ip绑定
protected-mode yes # 打开保护模式
port 6381 # 从机6381端口
slaveof 192.168.0.159 6379 # 加上主机的ip和端口,等会儿docker启动redis的时候,使用的network是host,所以ip可以确定
masterauth 123456 # 从机也有密码,加上验证
requirepass 123456 # 验证密码
3. 启动redis
- 首先启动主机
docker run \
-v /dockerRedis/redis:/usr/local/etc/redis \ # 绑定数据卷,主机的redis.conf放到本地的/dockerRedis/redis目录中,它会同步到容器中
-v /dockerRedis/data:/data \ # 持久化数据
--name redis \
--network host \ # 使用host
-d redis:4.0 \
redis-server /usr/local/etc/redis/redis.conf \ # 以配置文件方式启动
--appendonly yes
- 启动从机1
docker run \
-v /dockerRedis80/redis:/usr/local/etc/redis \ # 绑定数据卷,从机1的redis.conf放到本地的/dockerRedis80/redis目录中,它会同步到容器中
-v /dockerRedis80/data:/data \ # 持久化数据
--name redis80 \
--network host \ # 使用host
-d redis:4.0 \
redis-server /usr/local/etc/redis/redis.conf \ # 以配置文件方式启动
--appendonly yes
- 启动从机2
docker run \
-v /dockerRedis81/redis:/usr/local/etc/redis \ # 绑定数据卷,从机2的redis.conf放到本地的/dockerRedis81/redis目录中,它会同步到容器中
-v /dockerRedis81/data:/data \ # 持久化数据
--name redis81 \
--network host \ # 使用host
-d redis:4.0 \
redis-server /usr/local/etc/redis/redis.conf \ # 以配置文件方式启动
--appendonly yes
- 查看是否启动成功
[root@localhost redis]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ba3bf2106517 redis:4.0 "docker-entrypoint.s…" 6 hours ago Up About an hour redis81
12974de744bb redis:4.0 "docker-entrypoint.s…" 6 hours ago Up 27 minutes redis80
889f5f75d2a8 redis:4.0 "docker-entrypoint.s…" 6 hours ago Up 34 minutes redis
-
登陆redis客户端查看主从是否成功
- 主机
[root@localhost ~]# docker exec -it redis redis-cli 127.0.0.1:6379> auth 123456 OK 127.0.0.1:6379> info replication # Replication role:master # master角色 connected_slaves:2 # 连接的从机数量 slave0:ip=192.168.0.159,port=6381,state=online,offset=792339,lag=1 # 从机6381 slave1:ip=192.168.0.159,port=6380,state=online,offset=792195,lag=1 # 从机6380 master_replid:36b946e492eb817705b37c850bf8556136df22b7 master_replid2:2d958c8ec641afb7144b329ec0ee6d54a9eb389d master_repl_offset:792497 second_repl_offset:396598 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:333961 repl_backlog_histlen:458537
- 从机(另一个从机信息差不多)
127.0.0.1:6380> [root@localhost ~]# docker exec -it redis80 redis-cli -p 6380 127.0.0.1:6380> auth 123456 OK 127.0.0.1:6380> info replication # Replication role:slave # slave角色 master_host:192.168.0.159 # 主机ip master_port:6379 # 主机端口 master_link_status:up # 连接状态 master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_repl_offset:831773 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:36b946e492eb817705b37c850bf8556136df22b7 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:831773 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:405043 repl_backlog_histlen:426731
4. 启动哨兵
- 哨兵
sentinel.conf
配置文件(三个哨兵配置文件都一样,唯一不同的就是上面的端口号,分别为主机的26379和两个从机的26380、26381)
port 26379
sentinel monitor masterRedis 192.168.0.159 6379 2
sentinel auth-pass masterRedis 123456
-
将三个
sentinel.conf
配置文件分别放在刚才放redis.conf
的三个文件夹中,它们会自动同步到docker容器内。 -
启动主机哨兵
使用命令: docker exec -it redis redis-sentinel /usr/local/etc/redis/sentinel.conf
- 为了直接看到启动效果,我在前台运行,然后用
Ctrl + P + Q
快捷键,不关闭容器的情况下退出。 - 这里启动哨兵的方式,是用刚才的Redis主机容器,新开窗口启动,接下开两个从机也是相同的方式。
- 为了直接看到启动效果,我在前台运行,然后用
[root@localhost redis]# docker exec -it redis redis-sentinel /usr/local/etc/redis/sentinel.conf
24:X 17 Dec 07:04:00.734 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
24:X 17 Dec 07:04:00.734 # Redis version=4.0.14, bits=64, commit=00000000, modified=0, pid=24, just started
24:X 17 Dec 07:04:00.734 # Configuration loaded
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 4.0.14 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 24
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
24:X 17 Dec 07:04:00.735 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
24:X 17 Dec 07:04:00.736 # Sentinel ID is 0a417519ee7d4f31a2fb2fe6c62e9affdbe8c1c4
24:X 17 Dec 07:04:00.736 # +monitor master masterRedis 192.168.0.159 6379 quorum 2
# 哨兵已经发现两个从机
24:X 17 Dec 07:04:00.737 * +slave slave 192.168.0.159:6380 192.168.0.159 6380 @ masterRedis 192.168.0.159 6379
24:X 17 Dec 07:04:00.739 * +slave slave 192.168.0.159:6381 192.168.0.159 6381 @ masterRedis 192.168.0.159 6379
- 80从机哨兵启动
使用命令: docker exec -it redis80 redis-sentinel /usr/local/etc/redis/sentinel.conf
[root@localhost redis]# docker exec -it redis80 redis-sentinel /usr/local/etc/redis/sentinel.conf
17:X 17 Dec 07:04:17.515 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
17:X 17 Dec 07:04:17.515 # Redis version=4.0.14, bits=64, commit=00000000, modified=0, pid=17, just started
17:X 17 Dec 07:04:17.515 # Configuration loaded
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 4.0.14 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26380
| `-._ `._ / _.-' | PID: 17
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
17:X 17 Dec 07:04:17.516 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
17:X 17 Dec 07:04:17.517 # Sentinel ID is ebde833c6f6ab79f2fd3311c965104a58080b5da
17:X 17 Dec 07:04:17.517 # +monitor master masterRedis 192.168.0.159 6379 quorum 2
17:X 17 Dec 07:04:17.518 * +slave slave 192.168.0.159:6380 192.168.0.159 6380 @ masterRedis 192.168.0.159 6379
17:X 17 Dec 07:04:17.518 * +slave slave 192.168.0.159:6381 192.168.0.159 6381 @ masterRedis 192.168.0.159 6379
# 哨兵之间也会互相监控
17:X 17 Dec 07:04:19.213 * +sentinel sentinel 0a417519ee7d4f31a2fb2fe6c62e9affdbe8c1c4 192.168.0.159 26379 @ masterRedis 192.168.0.159 6379
- 81从机哨兵启动
使用命令: docker exec -it redis81 redis-sentinel /usr/local/etc/redis/sentinel.conf
[root@localhost redis]# docker exec -it redis81 redis-sentinel /usr/local/etc/redis/sentinel.conf
17:X 17 Dec 07:04:27.655 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
17:X 17 Dec 07:04:27.655 # Redis version=4.0.14, bits=64, commit=00000000, modified=0, pid=17, just started
17:X 17 Dec 07:04:27.655 # Configuration loaded
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 4.0.14 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26381
| `-._ `._ / _.-' | PID: 17
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
17:X 17 Dec 07:04:27.656 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
17:X 17 Dec 07:04:27.658 # Sentinel ID is 9b9cfdd11bf140aff61e94ec28d54f11b38f7c71
17:X 17 Dec 07:04:27.658 # +monitor master masterRedis 192.168.0.159 6379 quorum 2
17:X 17 Dec 07:04:27.658 * +slave slave 192.168.0.159:6380 192.168.0.159 6380 @ masterRedis 192.168.0.159 6379
17:X 17 Dec 07:04:27.659 * +slave slave 192.168.0.159:6381 192.168.0.159 6381 @ masterRedis 192.168.0.159 6379
# 三个哨兵互相监控
17:X 17 Dec 07:04:27.682 * +sentinel sentinel ebde833c6f6ab79f2fd3311c965104a58080b5da 192.168.0.159 26380 @ masterRedis 192.168.0.159 6379
17:X 17 Dec 07:04:29.373 * +sentinel sentinel 0a417519ee7d4f31a2fb2fe6c62e9affdbe8c1c4 192.168.0.159 26379 @ masterRedis 192.168.0.159 6379
做完这一步,Redis的一主二从三哨兵已经完成,这个时候可以测试一下,停掉主机,会以投票的方式在两个从机中选出新的主机来,重启启动原来的主机后,它会变为从机。
SpringBoot2.0整合
- 在RedisAutoConfiguration中,导入了两个连接配置,我在使用的时候,redis没有密码并且关闭保护模式的情况下正常,但是加了密码就不能正常连接,所以我干脆将两个都排除,自己再重新添加jedis依赖,这样就一切正常了
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
- pom配置文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
- yml配置
spring:
redis:
sentinel:
master: masterRedis # master哨兵名称
nodes: # 哨兵节点
- 192.168.0.159:26379
- 192.168.0.159:26380
- 192.168.0.159:26381
password: 123456 # 密码
database: 0 # 数据库索引
timeout: 5000ms # 连接超时时间
jedis:
pool: # 可以查看api或者源码自己修改,这里只是例子
max-active: 8 # 最大连接数
max-wait: -1 # 最大阻塞等待时间(负数表示没限制)
max-idle: 8 # 最大空闲
min-idle: 0 # 最小空闲
- 修改默认的序列化器,这样在客户端查看的时候,就是json字符串
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.nio.charset.Charset;
/**
* @Description: 要实现对象的缓存,定义自己的序列化和反序列化器。比如使用阿里的fastjson来实现
*/
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
public FastJsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (null == t) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (null == bytes || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return (T) JSON.parseObject(str, clazz);
}
}
- SpringBoot2.0的redis配置类
/**
* @Description: Redis配置类
*/
@EnableCaching
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//使用fastjson序列化
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
// value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
// 配置序列化(解决乱码的问题),这里设置为10天过期
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(60L * 60L * 24L * 10L))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer))
.disableCachingNullValues();
// 添加信任,不然会报【com.alibaba.fastjson.JSONException: autoType is not support.】的错误
ParserConfig.getGlobalInstance().addAccept("com.lgz.redis.");
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
}