验证Lettuce在单连接上进行多路复用

2024-01-12 21:04

本文主要是介绍验证Lettuce在单连接上进行多路复用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 配置 RedisTemplate
  • 验证blocking操作在独立连接上进行
  • 验证单tcp连接的多路复用

redis multiplexing机制类似http2,在存在并发请求时能减少大量通讯延迟,但不支持blocking相关的操作,如BLPOP

配置 RedisTemplate

RedisTemplate自动根据操作类型,选择是在单连接上进行多路复用,还是申请新的连接/等待空闲连接

@Configuration
public class RedisTemplateConfig {@Beanpublic LettuceConnectionFactory lettuceConnectionFactory(@Value("${redis.cluster}") String address,@Value("${redis.password}") String password) {// 配置连接池管理var poolConfig = new GenericObjectPoolConfig<StatefulRedisClusterConnection<String, String>>();poolConfig.setMaxTotal(20);poolConfig.setMaxIdle(20);poolConfig.setMinIdle(2);poolConfig.setTestWhileIdle(true);poolConfig.setMinEvictableIdleDuration(Duration.ofMillis(60000));poolConfig.setTimeBetweenEvictionRuns(Duration.ofMillis(30000));poolConfig.setNumTestsPerEvictionRun(-1);// 配置客户端行为var clientConfig = LettucePoolingClientConfiguration.builder().clientOptions(ClusterClientOptions.builder().autoReconnect(true).pingBeforeActivateConnection(true).socketOptions(SocketOptions.builder().connectTimeout(Duration.ofSeconds(3)).build()).timeoutOptions(TimeoutOptions.builder().fixedTimeout(Duration.ofSeconds(3)).build()).topologyRefreshOptions(ClusterTopologyRefreshOptions.builder().enableAdaptiveRefreshTrigger(RefreshTrigger.MOVED_REDIRECT,RefreshTrigger.PERSISTENT_RECONNECTS).adaptiveRefreshTriggersTimeout(Duration.ofSeconds(30)).build()).build()).poolConfig(poolConfig).build();// 配置集群连接信息var redisConfig = new RedisClusterConfiguration();redisConfig.setMaxRedirects(5);redisConfig.setPassword(password);String[] serverArray = address.split(",|,|;|;");// 获取服务器数组Set<RedisNode> nodes = new HashSet<>();for (String ipPort : serverArray) {nodes.add(RedisNode.fromString(ipPort));}redisConfig.setClusterNodes(nodes);return new LettuceConnectionFactory(redisConfig, clientConfig);}@Beanpublic StringRedisTemplate redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {return new StringRedisTemplate(lettuceConnectionFactory);}
}

验证blocking操作在独立连接上进行

实现blocking LPOP操作的方法在opsForList()里;
并发100压测期间查看客户端本地的tcp连接,可以看到和每个redis节点都建立了大量连接;
证明RedisTemplate没有选择让不同并发线程共用同一个StatefulConnection

    @Testpublic void blpop() throws Exception {long start = System.currentTimeMillis();AtomicLong err = new AtomicLong();int maxThreads = 100;Semaphore semaphore = new Semaphore(maxThreads);for (int i = 0; i < maxThreads; i++) {final int threadnum = i + 1;semaphore.acquire(1);new Thread(new Runnable() {@Overridepublic void run() {try {template.opsForList().leftPop("test" + threadnum, 2, TimeUnit.SECONDS);} catch (Exception ex) {log.error("leftPop", ex);err.addAndGet(1L);} finally {semaphore.release(1);}}}).start();}semaphore.acquire(maxThreads);long end = System.currentTimeMillis();log.info("耗时{}ms, 错误{}", end - start, err.get());}

验证单tcp连接的多路复用

发起100个线程,每个线程连续进行1000次读写操作;
执行期间查看客户端本地的tcp连接,可以看到只建立了一个和redis节点的连接;
每个线程的指令并发地在同一个tcp连接上发出和响应,一次请求+响应实际相当于http2的一路stream

@Slf4j
@EnableAutoConfiguration(exclude = { RedisAutoConfiguration.class })
@SpringBootTest(classes = { RedisTemplateConfig.class })
public class RedisTemplateTest {@AutowiredStringRedisTemplate template;@Testpublic void getSet() throws Exception {long start = System.currentTimeMillis();int maxThreads = 100;long maxMessagess = 1000;AtomicLong err = new AtomicLong();AtomicLong num = new AtomicLong();Semaphore semaphore = new Semaphore(maxThreads);for (int i = 0; i < maxThreads; i++) {final int threadnum = i + 1;semaphore.acquire(1);new Thread(new Runnable() {@Overridepublic void run() {int j = 0;try {for (; j < maxMessagess; j++) {String key = "thread" + threadnum + "test" + j;String value = "test" + j;template.opsForValue().set(key, value, 1, TimeUnit.SECONDS);assertEquals(value, template.opsForValue().get(key));}} finally {num.addAndGet(j);semaphore.release(1);}}}).start();}semaphore.acquire(maxThreads);long end = System.currentTimeMillis();double rate = 1000d * num.get() / (end - start);log.info("每秒发送并读取消息{}; 耗时{}ms, 累计发送{}", rate, end - start, num.get());}

RedisTemplate屏蔽了哪些并发命令可以共用连接的决策难点,所以不要自行使用Lettuce客户端获取连接或从连接池申请连接。

这篇关于验证Lettuce在单连接上进行多路复用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/599159

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

Java 连接Sql sever 2008

Java 连接Sql sever 2008 /Sql sever 2008 R2 import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class TestJDBC

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

实例:如何统计当前主机的连接状态和连接数

统计当前主机的连接状态和连接数 在 Linux 中,可使用 ss 命令来查看主机的网络连接状态。以下是统计当前主机连接状态和连接主机数量的具体操作。 1. 统计当前主机的连接状态 使用 ss 命令结合 grep、cut、sort 和 uniq 命令来统计当前主机的 TCP 连接状态。 ss -nta | grep -v '^State' | cut -d " " -f 1 | sort |

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

easyui同时验证账户格式和ajax是否存在

accountName: {validator: function (value, param) {if (!/^[a-zA-Z][a-zA-Z0-9_]{3,15}$/i.test(value)) {$.fn.validatebox.defaults.rules.accountName.message = '账户名称不合法(字母开头,允许4-16字节,允许字母数字下划线)';return fal

easyui 验证下拉菜单select

validatebox.js中添加以下方法: selectRequired: {validator: function (value) {if (value == "" || value.indexOf('请选择') >= 0 || value.indexOf('全部') >= 0) {return false;}else {return true;}},message: '该下拉框为必选项'}