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

这篇具有很好参考价值的文章主要介绍了验证Lettuce在单连接上进行多路复用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


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

配置 RedisTemplate

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

@Configuration
public class RedisTemplateConfig {
   @Bean
   public 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);
   }

   @Bean
   public StringRedisTemplate redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
       return new StringRedisTemplate(lettuceConnectionFactory);
   }
}

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

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

    @Test
    public 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() {
                @Override
                public void run() {
                    try {
                        // 这里是blocking LPOP
                        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());
    }

Lettuce在这个场景下使用一个NIO selector/multiplexer来收发多个tcp连接上的消息,但是在单个tcp连接上没有使用全双工通讯和multiplexing(多路复用);
Lettuce的StatefulConnection是线程安全的,如果多线程共用一个StatefulConnection来执行blocking LPOP操作,那么会串行执行,严重影响执行效率(可通过操作Lettuce原生接口进行验证)

验证单tcp连接的多路复用

发起100个线程,每个线程连续进行1000次setex + get操作;
执行期间查看客户端本地的tcp连接,可以看到只建立了一个和redis节点的连接;
redis通讯协议在tcp全双工的基础上实现了多路复用,支持多个指令随时并发地在同一个tcp连接上发出和响应,且每个指令的发出和响应互不干扰,与http2的各路stream互不干扰类似;
如果和使用半双工通讯的Jedis进行对比,需要配置Jedis连接池maxTotal和maxIdle连接数都到100,才能有相同通讯效率

@Slf4j
@EnableAutoConfiguration(exclude = { RedisAutoConfiguration.class })
@SpringBootTest(classes = { RedisTemplateConfig.class })
public class RedisTemplateTest {
    @Autowired
    StringRedisTemplate template;

    @Test
    public 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() {
                @Override
                public 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客户端获取连接或从连接池申请连接。文章来源地址https://www.toymoban.com/news/detail-792520.html

到了这里,关于验证Lettuce在单连接上进行多路复用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 驱动开发--多路复用-信号

     每个进程都有一个描述符数组,这个数组的下标为描述符, 描述符的分类: 文件描述符:设备文件、管道文件 socket描述符 select:位运算实现 监控的描述符数量有限(32位机1024,64位机2048) 效率差 poll:链表实现,监控的描述符数量不限 效率差 epoll:效率最高,监控的描述

    2024年01月22日
    浏览(38)
  • 说说IO多路复用

    IO多路复用 I/O multiplexing 这里面的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态(对应空管塔里面的Fight progress strip槽)来同时管理多个I/O流。直白点说:多路指的是多个socket连接,复用指的是复用一个线程进行管理。发明它的原因,是尽量多的提高服务

    2024年02月09日
    浏览(38)
  • IO多路复用详解

    在IO多路复用模型中,引入了一种新的系统调用,查询IO的就绪状态。在Linux系统中,对应的系统调用为select/poll/epoll系统调用。通过该系统调用,一个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是内核缓冲区可读/可写),内核能够将就绪的状态返回给应用程序

    2024年02月08日
    浏览(48)
  • IO多路复用练习

    一、通过select搭建TCP服务器 二、通过select搭建TCP客户端 三、通过poll搭建客户端

    2024年02月12日
    浏览(32)
  • 基于TCP的多路复用

    目前支持I/O多路复用的系统调用有select,pselect,poll,epoll。与多进程和多线程技术相 比, I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程, 也不必维护这些进 程/线程,从而大大减小了系统的开销。 I/O多路复用就是通过一种机制,一个进程可以监视多个

    2024年02月03日
    浏览(32)
  • 操作系统- IO多路复用

    1) IO多路复用是操作系统的原理,但是很多中间件的实现都是基于它去做的,IO多复用需要 知道整个链路是样子的,输入是什么,输出是什么 2) 了解IO多路复用作用的位置是哪里 3.1.1 IO多路复用的输入 IO多路复用的输入是Socket文件 3.1.2 IO多路复用的输出 IO多路复用的输出是读

    2023年04月08日
    浏览(32)
  • 计算机网络——多路复用技术

            多路复用是一种技术,允许在一个传输介质上传输多个信号或信息流。这种技术对于优化资源使用和增加网络的传输能力至关重要。         以下是对所提到的不同类型的多路复用的详细解释:         在FDM中,每个信号在同一个通道上以不同的频率传输

    2024年01月23日
    浏览(47)
  • Kotlin 协程 - 多路复用 select()

            又叫选择表达式,是一个挂起函数,可以同时等待多个挂起结果,只取用最快恢复的那个值(即多种方式获取数据,哪个更快返回结果就用哪个)。         同时到达 select() 会优先选择先写子表达式,想随机(公平)的话使用 selectUnbiased() 替换 。         能

    2024年02月10日
    浏览(44)
  • C语言 select()多路复用

            这这段代码主要实现TCP服务端时时监听客户机的连接,用实现一对多通行;   SELECT(2)                                                        Linux Programmer\\\'s Manual                                                        SELECT(2) NAME        select, psele

    2024年02月12日
    浏览(38)
  • 网络模型与 IO 多路复用

      socket也称作“套接字”,用于描述IP地址和端口,是一个通信链路的描述符。应用程序通常通过“套接字”向对端发出请求或者应答网络请求。   socket是连接运行在网络上的两个程序之间的通信端点。通信的两端都有socket,它是一个通道,数据在两个socket之间进行传输

    2024年02月01日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包