一、哨兵模式和集群模式 从节点 的区别
- 哨兵模式中的从节点默认是可读的。
- 集群模式中的从节点默认是不可读的,只是主节点的热备。
如果想要从集群模式中的从节点读取数据,需要客户端在建立连接之后先发送一个readonly命令。
二、lettuce对集群模式的处理
- 建立连接后,先查询集群信息,缓存哈希分槽,以后如果没有拓扑刷新就直接使用缓存的哈希分槽定位机器,不会每次随便连一个,等着服务器重定向;
io/lettuce/core/cluster/models/partitions/Partitions.java
public void updateCache() {
synchronized (partitions) {
if (partitions.isEmpty()) {
this.slotCache = EMPTY;
this.nodeReadView = Collections.emptyList();
return;
}
RedisClusterNode[] slotCache = new RedisClusterNode[SlotHash.SLOT_COUNT];
List<RedisClusterNode> readView = new ArrayList<>(partitions.size());
for (RedisClusterNode partition : partitions) {
readView.add(partition);
partition.forEachSlot(i -> slotCache[i] = partition);
}
this.slotCache = slotCache;
this.nodeReadView = Collections.unmodifiableCollection(readView);
}
}
- 如果连接的是从节点,会先发送一个readonly命令,然后这个连接以后就可以从从节点读取数据了;
io/lettuce/core/cluster/PooledClusterConnectionProvider.java
@Override
public ConnectionFuture<StatefulRedisConnection<K, V>> apply(ConnectionKey key) {
if (key.nodeId != null && getPartitions().getPartitionByNodeId(key.nodeId) == null) {
clusterEventListener.onUnknownNode();
throw connectionAttemptRejected("node id " + key.nodeId);
}
if (key.host != null && partitions.getPartition(key.host, key.port) == null) {
clusterEventListener.onUnknownNode();
if (validateClusterNodeMembership()) {
throw connectionAttemptRejected(key.host + ":" + key.port);
}
}
ConnectionFuture<StatefulRedisConnection<K, V>> connection = delegate.apply(key)