聊聊lettuce的sentinel连接 1
序
本文主要研究一下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
聊聊lettuce的sentinel连接 1相关推荐
- 聊聊lettuce的sentinel连接
为什么80%的码农都做不了架构师?>>> 序 本文主要研究一下lettuce的sentinel连接 RedisClient.connectSentinel lettuce-co ...
- 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提供通用的连接 ...
最新文章
- 产生所有排列---旋转法------2013年1月22日
- 大型网站技术架构(二)架构模式
- 操作系统三: 地址空间与地址生成
- 编码(encode)问题
- [POJ2155] Matrix(二维线段树,树套树)
- C4C Product Price List的模型中和有效期相关的两个字段
- C++基础07-类之静态成员变量和成员函数
- 为基于spring-boot的应用添加根据运行时操作系统环境来提示用户选择active profile的功能...
- 表单内如何直接贴图而不用上传图片_重磅更新|偷偷告诉你,表单大师官网改版啦啦啦啦...
- nvidia TX2 CUDA yolov5环境搭建
- winxp一键锁定计算机,WinXP下锁定计算机的3种方法
- [置顶] JQUERY一些注意事项
- pytorch convLSTM实现
- jdbc sql拼接字符串
- linux cups网络打印机,基于CUPS的网络打印服务器
- 一帮一 分数 15作者 陈越单位 浙江大学
- [Other]B树 B+树 B*树 - 三大名树的基础简介
- xml文件格式化脚本
- 微信小程序简易音频播放器(wx.getBackgroundAudioManager())
- 微信公众号点击列表进入详情页