SpringBoot对接高可用Redis的情况和配置方式
Redis 高可用分两个方式:主从哨兵模式或者Cluster集群
SpringBoot 版本
2.6.8
主从哨兵模式
常见的部署是一主二从三哨兵模式,一个redis节点主节点,承担写+读的责任。两个redis节点,作为只读节点,不承担写入责任,三个redis节点,通过特殊的启动模式,作为监控节点,监控主节点的实例状态。
特性:高可用、部分高并发,主从节点数据完全一致
缺点:高并发特性不明显
优点:支持性好,可无缝衔接具体项目,完美支持lua脚本
Spring Boot对接
1 | #主节点的名称 |
Cluster集群
常见的部署是三主三从,三个redis节点,作为主节点,承担写+读的责任。三个redis节点,从节点提供数据读能力,不承担写入责任。Cluster集群式无中心的架构,六者之间相互监控,当有主节点实例状态出问题,从节点自动顶上
特性:高可用、高并发,数据分片,三个主节点数据不一致
优点:高并发
缺点:数据分片,导致原生不支持mset,mget,pipeline等批量操作,部分支持lua脚本
Spring Boot对接
对接尽量使用
lettuce,不要使用jediscluster集群原生不支持批量操作lettuce和jedis都对其进行二次封装,能在cluster集群中使用mset,mget1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41mset mget
//redis.clients.jedis.JedisCluster 2013
public String mset(final String... keysvalues) {
String[] keys = new String[keysvalues.length / 2];
for (int keyIdx = 0; keyIdx < keys.length; keyIdx++) {
keys[keyIdx] = keysvalues[keyIdx * 2];
}
return new JedisClusterCommand<String>(connectionHandler, maxAttempts, maxTotalRetriesDuration) {
public String execute(Jedis connection) {
return connection.mset(keysvalues);
}
}.run(keys.length, keys);
}
// io.lettuce.core.cluster.RedisAdvancedClusterAsyncCommandsImpl<K, V> 350
public RedisFuture<String> mset(Map<K, V> map) {
Map<Integer, List<K>> partitioned = SlotHash.partition(codec, map.keySet());
if (partitioned.size() < 2) {
return super.mset(map);
}
Map<Integer, RedisFuture<String>> executions = new HashMap<>();
for (Map.Entry<Integer, List<K>> entry : partitioned.entrySet()) {
Map<K, V> op = new HashMap<>();
entry.getValue().forEach(k -> op.put(k, map.get(k)));
RedisFuture<String> mset = super.mset(op);
executions.put(entry.getKey(), mset);
}
return MultiNodeExecution.firstOfAsync(executions);
}
lettuce还支持pipeline,jedis不支持,会直接抛出异常1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// pipeline
// org.springframework.data.redis.connection.lettuce.LettuceConnection 490
public void openPipeline() {
if (!isPipelined) {
isPipelined = true;
ppline = new ArrayList<>();
flushState = this.pipeliningFlushPolicy.newPipeline();
flushState.onOpen(this.getOrCreateDedicatedConnection());
}
}
// org.springframework.data.redis.connection.jedis.JedisClusterConnection 849
public void openPipeline() {
throw new UnsupportedOperationException("Pipeline is currently not supported for JedisClusterConnection.");
}
lua脚本,如果不是批量操作,或者此次批量操作涉及的key能分片到同一台redis上,可以执行
1 | #六个节点的地址 |