聊聊lettuce的sentinel连接
为什么80%的码农都做不了架构师?>>>
序
本文主要研究一下lettuce的sentinel连接
RedisClient.connectSentinel
lettuce-core-5.0.4.RELEASE-sources.jar!/io/lettuce/core/RedisClient.java
private <K, V> StatefulRedisSentinelConnection<K, V> connectSentinel(RedisCodec<K, V> codec, RedisURI redisURI,Duration timeout) {assertNotNull(codec);checkValidRedisURI(redisURI);ConnectionBuilder connectionBuilder = ConnectionBuilder.connectionBuilder();connectionBuilder.clientOptions(ClientOptions.copyOf(getOptions()));connectionBuilder.clientResources(clientResources);DefaultEndpoint endpoint = new DefaultEndpoint(clientOptions);StatefulRedisSentinelConnectionImpl<K, V> connection = newStatefulRedisSentinelConnection(endpoint, codec, timeout);logger.debug("Trying to get a Redis Sentinel connection for one of: " + redisURI.getSentinels());connectionBuilder.endpoint(endpoint).commandHandler(() -> new CommandHandler(clientOptions, clientResources, endpoint)).connection(connection);connectionBuilder(getSocketAddressSupplier(redisURI), connectionBuilder, redisURI);if (clientOptions.isPingBeforeActivateConnection()) {connectionBuilder.enablePingBeforeConnect();}if (redisURI.getSentinels().isEmpty() && (isNotEmpty(redisURI.getHost()) || !isEmpty(redisURI.getSocket()))) {channelType(connectionBuilder, redisURI);try {getConnection(initializeChannelAsync(connectionBuilder));} catch (RuntimeException e) {connection.close();throw e;}} else {boolean connected = false;boolean first = true;Exception causingException = null;validateUrisAreOfSameConnectionType(redisURI.getSentinels());for (RedisURI uri : redisURI.getSentinels()) {if (first) {channelType(connectionBuilder, uri);first = false;}connectionBuilder.socketAddressSupplier(getSocketAddressSupplier(uri));if (logger.isDebugEnabled()) {SocketAddress socketAddress = SocketAddressResolver.resolve(uri, clientResources.dnsResolver());logger.debug("Connecting to Redis Sentinel, address: " + socketAddress);}try {getConnection(initializeChannelAsync(connectionBuilder));connected = true;break;} catch (Exception e) {logger.warn("Cannot connect Redis Sentinel at " + uri + ": " + e.toString());causingException = e;}}if (!connected) {connection.close();throw new RedisConnectionException("Cannot connect to a Redis Sentinel: " + redisURI.getSentinels(),causingException);}}if (LettuceStrings.isNotEmpty(redisURI.getClientName())) {connection.setClientName(redisURI.getClientName());}return connection;}
- connectSentinel方法,会遍历sentinel,挨个取master获取连接,如果连接不上或抛异常则继续用下一个sentinel获取
- 如果遍历完sentinel都抛异常,则最后抛出RedisConnectionException("Cannot connect to a Redis Sentinel: " + redisURI.getSentinels(),causingException)
- 这里会调用AbstractRedisClient的initializeChannelAsync方法
AbstractRedisClient.initializeChannelAsync
lettuce-core-5.0.4.RELEASE-sources.jar!/io/lettuce/core/AbstractRedisClient.java
/*** Connect and initialize a channel from {@link ConnectionBuilder}.** @param connectionBuilder must not be {@literal null}.* @return the {@link ConnectionFuture} to synchronize the connection process.* @since 4.4*/@SuppressWarnings("unchecked")protected <K, V, T extends RedisChannelHandler<K, V>> ConnectionFuture<T> initializeChannelAsync(ConnectionBuilder connectionBuilder) {SocketAddress redisAddress = connectionBuilder.socketAddress();if (clientResources.eventExecutorGroup().isShuttingDown()) {throw new IllegalStateException("Cannot connect, Event executor group is terminated.");}logger.debug("Connecting to Redis at {}", redisAddress);CompletableFuture<Channel> channelReadyFuture = new CompletableFuture<>();Bootstrap redisBootstrap = connectionBuilder.bootstrap();RedisChannelInitializer initializer = connectionBuilder.build();redisBootstrap.handler(initializer);clientResources.nettyCustomizer().afterBootstrapInitialized(redisBootstrap);CompletableFuture<Boolean> initFuture = initializer.channelInitialized();ChannelFuture connectFuture = redisBootstrap.connect(redisAddress);connectFuture.addListener(future -> {if (!future.isSuccess()) {logger.debug("Connecting to Redis at {}: {}", redisAddress, future.cause());connectionBuilder.endpoint().initialState();channelReadyFuture.completeExceptionally(future.cause());return;}initFuture.whenComplete((success, throwable) -> {if (throwable == null) {logger.debug("Connecting to Redis at {}: Success", redisAddress);RedisChannelHandler<?, ?> connection = connectionBuilder.connection();connection.registerCloseables(closeableResources, connection);channelReadyFuture.complete(connectFuture.channel());return;}logger.debug("Connecting to Redis at {}, initialization: {}", redisAddress, throwable);connectionBuilder.endpoint().initialState();Throwable failure;if (throwable instanceof RedisConnectionException) {failure = throwable;} else if (throwable instanceof TimeoutException) {failure = new RedisConnectionException("Could not initialize channel within "+ connectionBuilder.getTimeout(), throwable);} else {failure = throwable;}channelReadyFuture.completeExceptionally(failure);CompletableFuture<Boolean> response = new CompletableFuture<>();response.completeExceptionally(failure);});});return new DefaultConnectionFuture<T>(redisAddress, channelReadyFuture.thenApply(channel -> (T) connectionBuilder.connection()));}
- 这里initializeChannelAsync的时候,会调用connectionBuilder.socketAddress()方法,进而调用RedisClient的getSocketAddress方法
RedisClient.getSocketAddress
lettuce-core-5.0.4.RELEASE-sources.jar!/io/lettuce/core/RedisClient.java
protected SocketAddress getSocketAddress(RedisURI redisURI) throws InterruptedException, TimeoutException,ExecutionException {SocketAddress redisAddress;if (redisURI.getSentinelMasterId() != null && !redisURI.getSentinels().isEmpty()) {logger.debug("Connecting to Redis using Sentinels {}, MasterId {}", redisURI.getSentinels(),redisURI.getSentinelMasterId());redisAddress = lookupRedis(redisURI);if (redisAddress == null) {throw new RedisConnectionException("Cannot provide redisAddress using sentinel for masterId "+ redisURI.getSentinelMasterId());}} else {redisAddress = SocketAddressResolver.resolve(redisURI, clientResources.dnsResolver());}return redisAddress;}private SocketAddress lookupRedis(RedisURI sentinelUri) throws InterruptedException, TimeoutException, ExecutionException {try (StatefulRedisSentinelConnection<String, String> connection = connectSentinel(sentinelUri)) {return connection.async().getMasterAddrByName(sentinelUri.getSentinelMasterId()).get(timeout.toNanos(), TimeUnit.NANOSECONDS);}}
- getSocketAddress方法会调用lookupRedis方法,而lookupRedis方法则调用getMasterAddrByName方法,通过sentinel来获取master的ip地址
小结
- redis的sentinel类似于一个master的服务发现中心,假设master有故障,则通过sentinel获取新的master实现failover。
- 而sentinel部署多个来实现高可用,假设一个sentinel挂了,则client端使用下一个sentinel来获取master地址
doc
- lettuce Redis-Sentinel
转载于:https://my.oschina.net/go4it/blog/2050667
聊聊lettuce的sentinel连接相关推荐
- Sentinel 连接数据源
若要载入 Azure Sentinel,首先需要连接到数据源. Azure Sentinel 随附许多适用于 Microsoft 解决方案的现成可用的连接器,提供实时集成(包括 Microsoft 威 ...
- Redis Lettuce客户端异步连接池详解
前言 异步/非阻塞编程模型需要非阻塞API才能获得Redis连接.阻塞的连接池很容易导致阻塞事件循环并阻止您的应用程序进行处理的状态.Lettuce带有异步,非阻塞池实现,可与Lettuces异步连接 ...
- Redis中的Sentinel 连接使用
Jedis 连接Sentinel(JedisSentinelTest.java) master name 来自于sentinel.conf 的配置. private static JedisSenti ...
- 聊聊lettuce的shareNativeConnection参数
序 本文主要研究一下lettuce的shareNativeConnection参数 LettuceConnectionFactory spring-data-redis-2.0.10.RELEASE- ...
- Sentinel连接 Azure 活动日志中的数据
只需要单击一次即可将日志从Azure 活动日志流式传输到 azure Sentinel. 活动日志是一种订阅日志,可用于深入了解 Azure 中发生的订阅级别事件. 这包括从 Azure 资源管理器操 ...
- python连接redis sentinel集群
安装 python redis 客户端 pip install redis #!/usr/bin/env python # -*- coding:utf-8 -*-#!/usr/bin/env pyt ...
- python连接redis哨兵_python连接redis sentinel集群
#!/usr/bin/env python # -*- coding:utf-8 -*- #!/usr/bin/env python import redis from redis.sentinel ...
- 解决Redisson无法连接Sentinel, Netty查找DNS失败
前言 这里 redisson 的版本为 3.11.2, 对应 netty-all 的版本为 4.1.38.Final 如果这篇描述的方法不能解决问题,可以参考另外一篇 Redisson-3.8 查找D ...
- Lettuce连接池
Lettuce 连接被设计为线程安全,所以一个连接可以被多个线程共享,同时lettuce连接默认是自动重连.虽然连接池在大多数情况下是不必要的,但在某些用例中可能是有用的.lettuce提供通用的连接 ...
最新文章
- spring Ioc本质
- linux环境安全测评实验报告,linux第一次实验报告
- P4216 [SCOI2015]情报传递 LCA+树上主席树 离线操作
- 弹性地基梁板实用计算_强夯地基承载力原理及测试方法
- 解决App启动时白屏的问题
- “约见”面试官系列之常见面试题之第七十六篇之vue-router中的路由钩子函数基本用法 (建议收藏)
- pandas学习笔记三之处理丢失数据
- LeetCode 540 有序数组中的单一元素
- java的值传递和引用传递
- Ruby Tip:定义索引操作符
- dnf服务器字幕乱码win10系统,Windows10下输入法设置 教你避免DNF卡顿
- mariadb中文手册_mariadb中文手册
- 远程关闭计算机提示拒绝访问权限,win7系统远程关机拒绝访问的解决方法
- Cesium: 如何将倾斜摄影数据转换为3dTiles格式
- 2.5万字讲解DDD领域驱动设计,从理论到实践掌握DDD分层架构设计,赶紧收藏起来吧
- 树莓派3B+ 智能家居(HomeKit)
- 设备驱动安装不上怎么办?
- 神州信息与北京市地方金融监督管理局、房山区人民政府签署战略合作
- 大部分人都容易焦虑,那么应该如何对待焦虑呢?
- 报表中的地图怎么做?