在linux环境下,使用docker compose安装redis sentinel集群的搭建,需要准备的工作:
1.1安装docker
•下载安装docker:yum -y install docker
•启动docker服务:service docker start
•检查docker是否安装成功:docker version
1.2安装docker compose
•安装命令:sudo pip install -U docker-compose
如果在安装的过程中,出现连接超时的报错提示,可以使用如下命令解决:
•pip --default-timeout=100 install -U Pillow,如果未出现报错,则无需使用该命令
1.3安装redis镜像
•安装命令:docker pull redis
•查看安装是否成功命令:docker images
1.4在/usr/local/目录下创建redis-docker文件夹
•命令:mkdir redis-docker
在redis-docker目录下创建redis目录
•命令:mkdir redis
在redis文件夹下创建docker-compose.yml文件,实现redis一主二从,编写内容:
redis不加密的配置方式:
version: '3'
services:
master:
image: redis
container_name: redis-sentinel-master
ports:
- 6379:6379
volumes:
- ./data:/redisdata
slave1:
image: redis
container_name: redis-sentinel-slave-1
ports:
- 6380:6379
command: redis-server --slaveof redis-sentinel-master 6379
volumes:
- ./data:/redisdata
slave2:
image: redis
container_name: redis-sentinel-slave-2
ports:
- 6381:6379
command: redis-server --slaveof redis-sentinel-master 6379
volumes:
- ./data:/redisdata
redis加密的配置方式:
version: '3'
services:
master:
image: redis
container_name: redis-sentinel-master
command: redis-server --requirepass 123456
ports:
- 6379:6379
volumes:
- ./data:/redisdata
slave1:
image: redis
container_name: redis-sentinel-slave-1
ports:
- 6380:6379
command: redis-server --slaveof redis-sentinel-master 6379 --requirepass 123456 --masterauth 123456
volumes:
- ./data:/redisdata
slave2:
image: redis
container_name: redis-sentinel-slave-2
ports:
- 6381:6379
command: redis-server --slaveof redis-sentinel-master 6379 --requirepass 123456 --masterauth 123456
volumes:
- ./data:/redisdata
主节点的端口,最好和redis的默认端口,即6379保持一致
•启动redis,使用如下命令 挂在后台:docker-compose up -d
•如果使用失败了,可以使用如下命令查看日志,观察是什么原因造成的:
docker logs -f 容器Id
•停止redis:docker-compose down
或者
docker stop 容器Id
docker rm 容器Id
•进入主redis容器中,使用如下命令:docker exec -it 容器Id bash
•重启docker:systemctl restart docker
•查看docker集群状态:docker ps -a
如果修改过redis节点的端口和ip,一定要重启docker镜像
1.5在redis-docker文件夹下创建sentinel文件
•命令:mkdir redis-docker
在redis-docker目录下,编写docker-compose.yml,编写内容:
version: '3'
services:
sentinel1:
image: redis
container_name: redis-sentinel-sentinel1
ports:
- 26379:26379
command: redis-sentinel /usr/local/redis-docker/sentinel/sentinel.conf
volumes:
- ./sentinel1.conf:/usr/local/redis-docker/sentinel/sentinel.conf
sentinel2:
image: redis
container_name: redis-sentinel-sentinel2
ports:
- 26380:26379
command: redis-sentinel /usr/local/redis-docker/sentinel/sentinel.conf
volumes:
- ./sentinel2.conf:/usr/local/redis-docker/sentinel/sentinel.conf
sentinel3:
image: redis
container_name: redis-sentinel-sentinel3
ports:
- 26381:26379
command: redis-sentinel /usr/local/redis-docker/sentinel/sentinel.conf
volumes:
- ./sentinel3.conf:/usr/local/redis-docker/sentinel/sentinel.conf
1.6在redis-docker文件夹下编写sentinel.conf文件
sentinel.conf内容如下:
port 26379
dir /tmp
# 自定义集群名,其中 192.168.1.110 为 redis-master 的 ip,6379 为 redis-master 的端口,2 为最小投票数(因为有 3 台 Sentinel 所以可以设置成 2),我自己设置的主节点的ip为所在服务器的ip
sentinel monitor mymaster 192.168.1.110 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
执行如下命令,复制3份redis-sentinel配置文件
cp sentinel.conf sentinel1.conf
cp sentinel.conf sentinel2.conf
cp sentinel.conf sentinel3.conf
•启动redis-sentinel:docker-compose up -d
•查看redis-sentinel是否启动状态:docker-compose ps
•执行如下命令,查看从redis信息是否正常:sentinel slaves mymaster
•执行如下命令,查看redis主节点信息:sentinel master mymaster
名词 | 描述 |
---|---|
version | docker文件的版本 |
image | 指定容器镜像就是之前拉取的redis镜像 |
container_name | 给这个镜像起一个别名 |
restart | always:表名开机自启动 |
command | 相当于执行一些命令 (–requirepass 指定redis密码 --appendonly yes 这个命令是用于开启redis数据持久化) |
ports | 端口映射,将容器的端口映射到对应宿主机的端口 |
volumes | 数据卷的映射.因为一旦容器停止了那么里面的数据也没有.所以我们需要把这个数据文件放在外面,然后映射到容器中 |
#Redis集群哨兵模式
redisSentinel:
sentinelMaster: 192.168.1.110
masterName: mymaster
sentinelNodes: 192.168.1.110:26379,192.168.1.110:26380,192.168.1.110:26381
sentinelPort: 6379
maxIdle: 300
maxTotal: 1000
maxWaitMills: 1000
minEvictableIdleTimeMillis: 300000
numTestPerEvictionRun: 1024
timeBetweenEvictionRunMillis: 30000
testOnBorrow: true
testWhileIdle: true
哨兵模式下,redis集群相对来说特殊点,这种配置下,后端代码直接监控并连接哨兵节点信息,并不直接连接主节点;所以masterName和sentinel.conf配置文件中mymaster保持一致,否则后端会报错,这是我的理解,如果有不对的地方;sentinelMaster这个参数,可以不配置。
3.1.pom文件添加依赖,我使用的是jedis1.8.6版本:
org.springframework.boot
spring-boot-starter-data-redis
3.2创建redis集群连接池配置RedisSentinelPoolConfig.java
/**
* @Description:redis集群哨兵模式下,用于初始化连接池
* @Date: 2019/8/10 15:44
*/
@Configuration
public class RedisSentinelPoolConfig {
@Value("${redisSentinel.maxIdle}")
private Integer maxIdle;
@Value("${redisSentinel.maxTotal}")
private Integer maxTotal;
@Value("${redisSentinel.maxWaitMills}")
private Integer maxWaitMills;
@Value("${redisSentinel.minEvictableIdleTimeMillis}")
private Integer minEvictableIdleTimeMillis;
@Value("${redisSentinel.numTestPerEvictionRun}")
private Integer numTestPerEvictionRun;
@Value("${redisSentinel.timeBetweenEvictionRunMillis}")
private long timeBetweenEvictionRunMillis;
@Value("${redisSentinel.testOnBorrow}")
private boolean testOnBorrow;
@Value("${redisSentinel.testWhileIdle}")
private boolean testWhileIdle;
@Value("${redisSentinel.sentinelMaster}")
private String sentinelMaster;
@Value("${redisSentinel.masterName}")
private String masterName;
@Value("${redisSentinel.sentinelNodes}")
private String sentinelNodes;
@Value("${redisSentinel.sentinelPort}")
private String sentinelPort;
/*
* 初始化JedisPoolConfig连接池到spring容器内
*/
@Bean
public JedisPoolConfig jedisPoolConfig(){
JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
//最大空闲数
jedisPoolConfig.setMaxIdle(maxIdle*10);
//连接池的最大数据库连接数
jedisPoolConfig.setMaxTotal(maxTotal*10);
//最大建立连接等待时间
jedisPoolConfig.setMaxWaitMillis(maxWaitMills*10);
//逐出连接的最小空闲时间默认1800000毫秒(30分钟)
jedisPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
//每次逐出检查时,逐出的最大数目,如果为负数就是1/abs(n),默认为3
jedisPoolConfig.setNumTestsPerEvictionRun(numTestPerEvictionRun);
//逐出扫描的时间间隔(毫秒),如果为负数,则不运行逐出线程,默认为-1
jedisPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunMillis);
//是否从连接池中取出连接前进行检验,如果检验失败,则尝试从池中取出另一个
jedisPoolConfig.setTestOnBorrow(testOnBorrow);
//在空闲时检查有效性,默认为false
jedisPoolConfig.setTestWhileIdle(testWhileIdle);
return jedisPoolConfig;
}
/*
* 初始化集群节点到spring容器内
*/
@Bean
public RedisSentinelConfiguration redisSentinelConfiguration(){
RedisSentinelConfiguration configuration=new RedisSentinelConfiguration();
String[] host=sentinelNodes.split(Constants.COMMA);
for(String redisHost:host){
String[] item=redisHost.split(Constants.COLON);
String ip=item[0];
String port=item[1];
configuration.addSentinel(new RedisNode(ip,Integer.parseInt(port)));
}
configuration.setMaster(masterName);
return configuration;
}
}
3.3创建redis配置RedisConfiguration.java
/**
* redis配置
*
* @create 2018/8/10 17:25
*/
@Configuration
@EnableCaching
public class RedisConfiguration extends CachingConfigurerSupport {
@Autowired
private JedisPoolConfig jedisPoolConfig;
@Autowired
private RedisSentinelConfiguration redisSentinelConfiguration;
@Bean
public JedisConnectionFactory jedisConnectionFactory(){
JedisConnectionFactory jedisConnectionFactory=new JedisConnectionFactory(redisSentinelConfiguration,jedisPoolConfig);
//如果redis没设置密码,就不要传参数,否则会报错
// jedisConnectionFactory.setPassword(redisPassword);
return jedisConnectionFactory;
}
@Bean
public RedisTemplate redisTemplate(){
RedisTemplate template = new RedisTemplate ();
//设置开启事务
template.setEnableTransactionSupport(true);
//设置key序列化
StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setConnectionFactory(jedisConnectionFactory());
template.afterPropertiesSet();
return template;
}
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
//rcm.setDefaultExpiration(60);
return rcm;
}
}
3.4创建RedisSentinelTemplate.java,用于后端代码操作redis库
/**
* @Description:redis集群哨兵模式下,用于操作redis库
* @Date: 2019/8/10 15:44
*/
@Component
public class RedisSentinelTemplate {
@Autowired
private RedisTemplate redisTemplate;
public void set(String key ,Object value){
redisTemplate.opsForValue().set(key,value);
}
public void set(String key, Object obj, Long expiration) {
redisTemplate.opsForValue().set(key, obj, expiration, TimeUnit.SECONDS);
}
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
}
然后在业务模块注入RedisSentinelTemplate对象,即可进行数据的增删改查
在这里有一篇文章,写的也是这种搭建方式,写的也很不错,大家可以参考下
1: https://www.cnblogs.com/hckblogs/p/11186311.html
以上内容纯属原创,有些地方也是参考了网上不少教程;这篇文章纯属技术分享,不以任何盈利为目的,如果有侵权的地方,请私信我,我将会进行调整,谢谢!