文章目录
- 集群
- 创建网络
- 创建集群
- Redisson
- 导入依赖
- 配置
- 测试
- 问题
集群
使用Docker配置redis集群。
- 创建网络
- 编写配置文件
- 运行容器
- 构建集群
创建网络
网络名称redis(可自行更换)。
docker network create -d bridge --subnet 172.180.0.0/16 --gateway 172.180.0.1 redis
#查看网络状态
docker network ls
docker network inspect redis
创建集群
其余三个过程可以使用Shell脚本完成,rmredis. sh(移除容器),(创建配置文件,运行容器,创建集群)。从主机对应端口号6371~6376 (可自行配置)。
文件路径可以修改。
for port in $(seq 1 6)
do
echo "remove redis0${port}"
docker rm -f redis0${port}
rm -rf /home/zhangzhibo/redis/node-${port}
done
将主机ip修改成你的,路径同样可修改。
#!/bin/bash
for port in $(seq 1 6)
do
#创建配置文件
echo "this value is $port"
mkdir -p /home/zhangzhibo/redis/node-${port}/conf
touch /home/zhangzhibo/redis/node-${port}/conf/
cat << EOF > /home/zhangzhibo/redis/node-${port}/conf/
#端口
port 6379
#非保护模式
protected-mode no
#启用集群模式
cluster-enabled yes
cluster-config-file nodes-637${port}.conf
#超时时间
cluster-node-timeout 15000
#集群各节点IP地址,记得修改为你的ip地址
cluster-announce-ip 主机ip
#集群节点映射端口
cluster-announce-port 637${port}
#集群总线端口
cluster-announce-bus-port 1637${port}
#开启aof持久化策略
appendonly yes
#后台运行
#daemonize yes
#进程号存储
pidfile /var/run/redis_6379.pid
#外部访问
bind 0.0.0.0
#日志
logfile "redis${port}.log"
#密码
#requirepass 123456
EOF
#创建容器
echo "create redis0${port}"
#不使用docker部署 redis-server /home/zhangzhibo/redis/node-${port}/conf/
#使用docker部署
docker run -d --name redis0${port} -p 637${port}:6379 -p 1637${port}:16379 --network redis --ip 172.180.0.1${port} -v /home/zhangzhibo/redis/node-${port}/data:/data -v /home/zhangzhibo/redis/node-${port}/conf/:/etc/redis/ redis redis-server /etc/redis/
done
echo "create cluster"
#此条语句执行的前提是主机上也安装了redis。
#没安装,注释掉随机进入一个容器执行即可。
redis-cli --cluster create 主机ip:6371 主机ip:6372 主机ip:6373 主机ip:6374 主机ip:6375 主机ip:6376 --cluster-replicas 1
Redisson
使用redisson连接集群。
导入依赖
只需要导入redisson的spring-boot-starter,这个依赖中含有redis启动器。
<dependency>
<groupId></groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.17.3</version>
</dependency>
配置
只需要在/yml/yaml中编写配置即可。可查看RedissonAutoConfiguration官方自动配置类,该配置类有调用RedissonProperties与RedisProperties,可根据两个配置类的属性进行配置。
(如有需求可对RedissonAutoConfiguration内的方法进行重写)
spring:
redis:
timeout: 6000
cluster:
max-redirects: 3
nodes:
- redis://服务器主机ip:6371
- redis://服务器主机ip:6372
- redis://服务器主机ip:6373
- redis://服务器主机ip:6374
- redis://服务器主机ip:6375
- redis://服务器主机ip:6376
lettuce:
pool:
max-active: 1024 # 连接池最大连接数(默认为8,-1表示无限制 如果pool已经分配了超过max_active个jedis实例,则此时pool为耗尽)
max-wait: 10000 #最大等待连接时间,单位毫秒 默认为-1,表示永不超时,超时会抛出JedisConnectionException
max-idle: 10
min-idle: 5
shutdown-timeout: 100
RedissonAutoConfiguration中创建了两个Template,RedisTemplate<Object, Object>与StringRedisTemplate。可以看到这两个并不能满足我们的需求,我们需要的泛型是<String, Object>,同时还要在redis数据库中查看数据时不出现乱码,所以要自行配置并对存储的数据进行序列化处理。
当然也可以使用他给的RedisTemplate<Object, Object>,使用@Autowired注入便可使用。
在使用@Autowired注入RedisTemplate<Object, Object>过程中,可能会报错提示“无法通过类型注入”。可以使用@Resource或者 @Autowired+ @Qualifier(value=“XXX”)。
@Configuration
public class RedisTemplateConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new
Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new
StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
测试
测试时创建了User类,同时实现了序列化接口。
注入,测试
@Autowired
RedisTemplate<String, Object> redisTemplate;
@Test
void springbootRedisson() {
RedisConnection connection =
Objects.requireNonNull(redisTemplate.getConnectionFactory()).getConnection();
connection.flushDb();
User user = new User("zhangzhibo", 22);
redisTemplate.opsForValue().set("user",user);
System.out.println(redisTemplate.opsForValue().get("user"));
}
问题
场景:
使用docker run … -d redis redis-server /…/ 运行容器后,使用docker ps查看容器创建成功但并没有启动。
解决方法:
文件中的daemonize参数为yes导致,修改/home/redis/redis-master/ 中的daemonize 为no 。docker本身就是后台运行的,daemonize为yes两者会冲突
场景:
在项目中集成Redis,连接单机Redis时。Redis运行在docker中,在确认路径、代码编写没问题下连接失败
解决办法:
查看有没有启动Redis服务器。
redis的配置(或)中连接超时时间(毫秒)中设置不能为0,一般修改如下:=5000。
protected-mode yes 改为 protected-mode no (即该配置项表示是否开启保护模式,默认是开启,开启后Redis只会本地进行访问,拒绝外部访问)。
注释掉 bin127.0.0.1 即 #bin 127.0.0.1 (ps: 指定 redis 只接收来自于该 IP 地址的请求,如果不进行设置,那么将处理所有请求)。
如果在Redis中没有配置requirepass ,那么在(或)中就不要写。
场景:
在集群测试阶段,无法正常运行。并伴有“正确”的cluster-config-file输出,主节点(master)无法连接。
解决办法:
查看cluster-config-file输出,其中的ip地址为127.0.0.1或者自定义的网络地址。redisson会根据配置的网络ip进行连接。(使用Jedis连接也会出现同样的错误)
要更改配置文件
cluster-announce-ip 主机ip cluster-announce-port 容器内6379端口对应的主机端口 cluster-announce-bus-port 容器内16379端口对应的主机端口
容器内不一定是6379,依据你的配置而定。