Redis高级客户端Lettuce

使用注意:要求JDK8及以上,redis版本至少为2.6

官方文档:https://lettuce.io/core/release/reference/index.html#getting-started.get-it

1、Lettuce简介

Lettuce是一个基于netty和Reactor的可伸缩线程安全Redis客户端。Lettuce提供了同步、异步、反应式API来与Redis进行交互。

2、基本使用

Lettuce使用的时候主要依赖于以下四个组件:

① redisURI:连接信息。
② redisClient:Redis客户端,如果是集群模式,集群连接有一个定制的RedisClusterClient。
③ connection:Redis的连接。
④ redisCommands:Redis命令API接口,基本上覆盖了Redis发行版本的所有命令,提供了同步(sync)、异步(async)、反应式(reative)的调用方式。

maven

<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>5.1.8.RELEASE</version>
</dependency>

2.1 单机模式

2.1.1 同步(sync)

入门案例:

        /** 初始化四个组件 **/
        RedisURI redisUri = RedisURI.builder()
                .withHost("192.168.139.198")
                .withPort(6379)
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        RedisClient redisClient = RedisClient.create(redisUri);
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        RedisCommands<String, String> redisCommands = connection.sync();

        /** API的使用 **/
        String result = redisCommands.set("name", "gaojian");
        System.out.println(result);
        result = redisCommands.get("name");
        System.out.println(result);

        /** 关闭资源 **/
        connection.close();
        redisClient.shutdown();

可以通过如下配置设置超时时间

    SetArgs timeout = SetArgs.Builder.nx().ex(5);
    String result = redisCommands.set("name", "gaojian", timeout);

所有连接均从其RedisClient继承默认超时,超时默认为60秒,当非阻塞命令未能在超时到期之前返回结果时 ,抛出RedisException异常,可以在RedisClient或每个连接中更改(如上)。如果Redis响应错误,则同步方法将抛出RedisCommandExecutionException,异步连接不会引发异常。

Redis连接被设计为长期存在并且是线程安全的,如果连接丢失,将重新连接直到close()被调用。成功重新连接后,将(重新)发送尚未超时的未决命令,所以在应用程序的最后,才关闭连接,同时,关闭客户端实例以释放线程和资源。

2.1.2 异步(async)

异步方法可以更好的利用系统资源,而不是浪费线程等待网络或磁盘I / O。可以充分利用线程来执行其他工作。Lettuce通过在基于Netty的客户端 (多线程,事件驱动的I / O框架)上构建客户端来促进异步性。所有通信都是异步处理的。

        /** 初始化四个组件 **/
        RedisURI redisUri = RedisURI.builder()
                .withHost("192.168.139.198")
                .withPort(6379)
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        RedisClient redisClient = RedisClient.create(redisUri);
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        RedisAsyncCommands<String, String> asyncCommands = connection.async();

        /** API的使用 **/
        RedisFuture<String> future = asyncCommands.set("age", "18");
        future.get(10,TimeUnit.SECONDS);
        future.thenAccept(new Consumer<String>() {
    
    
            @Override
            public void accept(String value) {
    
    
                System.out.println(value);
            }
        });

        RedisFuture<String> redisFuture = asyncCommands.get("age");
        redisFuture.get(10,TimeUnit.SECONDS);
        redisFuture.thenAccept(new Consumer<String>() {
    
    
            @Override
            public void accept(String value) {
    
    
                System.out.println(value);
            }
        });

        /** 关闭资源 **/
        connection.close();
        redisClient.shutdown();

对get()方法(拉式)的调用至少会阻塞调用线程,直到计算出值为止,但在最坏的情况下会无限期地阻塞该线程,为了防止无限期的阻塞该线程,建议使用超时配置。

2.1.3 响应式(reactor)

笔者暂不对该方式进行描述

2.2集群模式

连接到Redis集群需要一个或多个初始种子节点。完整的群集拓扑视图(分区)是在第一个连接上获得的,因此不需要指定所有群集节点。指定多个种子节点有助于提高弹性,因为即使种子节点不可用,Lettuce仍可以连接群集。

注意:群集连接本身会使用节点连接来执行群集操作,如果阻止一个连接,则群集连接的所有其他用户可能会受到影响。

2.2.1 同步(sync)
        RedisURI node1 = RedisURI.create("192.168.139.172", 7000);
        RedisURI node2 = RedisURI.create("192.168.139.172", 7001);
        RedisURI node3 = RedisURI.create("192.168.139.172", 7002);
        RedisURI node4 = RedisURI.create("192.168.139.172", 7003);
        RedisURI node5 = RedisURI.create("192.168.139.172", 7004);
        RedisURI node6 = RedisURI.create("192.168.139.172", 7005);

        RedisClusterClient clusterClient =  RedisClusterClient.create(Arrays.asList(node1,node2,node3,node4,node5,node6));
        StatefulRedisClusterConnection<String, String> connection = clusterClient.connect();
        RedisAdvancedClusterCommands<String, String> clusterCommands = connection.sync();

        /** API的使用 **/
        String set = clusterCommands.set("name", "gaojian");
        System.out.println(set);

        String name = clusterCommands.get("name");
        System.out.println(name);

        connection.close();
        clusterClient.shutdown();
2.2.2 异步(async)
        RedisURI node1 = RedisURI.create("192.168.139.172", 7000);
        RedisURI node2 = RedisURI.create("192.168.139.172", 7001);
        RedisURI node3 = RedisURI.create("192.168.139.172", 7002);
        RedisURI node4 = RedisURI.create("192.168.139.172", 7003);
        RedisURI node5 = RedisURI.create("192.168.139.172", 7004);
        RedisURI node6 = RedisURI.create("192.168.139.172", 7005);

        RedisClusterClient clusterClient = RedisClusterClient.create(Arrays.asList(node1,node2,node3,node4,node5,node6));
        StatefulRedisClusterConnection<String, String> connection = clusterClient.connect();
        RedisAdvancedClusterAsyncCommands<String, String> asyncCommands = connection.async();

        /** API的使用 **/
        RedisFuture<String> future = asyncCommands.set("name", "gaojian");
        future.get(10,TimeUnit.SECONDS);
        future.thenAccept(new Consumer<String>() {
    
    
            @Override
            public void accept(String value) {
    
    
                System.out.println(value);
            }
        });

        RedisFuture<String> redisFuture = asyncCommands.get("name");
        redisFuture.get(10,TimeUnit.SECONDS);
        redisFuture.thenAccept(new Consumer<String>() {
    
    
            @Override
            public void accept(String value) {
    
    
                System.out.println(value);
            }
        });

        connection.close();
        clusterClient.shutdown();
2.2.3 反应式(reactor)

笔者暂不对该方式进行描述

2.3 连接池

Lettuce连接被设计为线程安全的,因此一个连接可以在多个线程之间共享,并且默认情况下,Lettuce连接会自动重新连接。在大多数情况下不需要连接池,但是Lettuce也是支持连接池的,连接池总会带来复杂性和维护成本。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.4.3</version>
</dependency>
        RedisClusterClient clusterClient = RedisClusterClient.create(RedisURI.create("192.168.139.198", 6379));

        GenericObjectPool<StatefulRedisClusterConnection<String, String>> pool = ConnectionPoolSupport
                .createGenericObjectPool(() -> clusterClient.connect(), new GenericObjectPoolConfig());

        StatefulRedisClusterConnection<String, String> connection = pool.borrowObject();
        String age = connection.sync().set("age", "123");
        System.out.println(age);
        connection.sync().blpop(10, "age");

        String age1 = connection.sync().get("age");
        System.out.println(age1);

        pool.close();
        clusterClient.shutdown();

猜你喜欢

转载自blog.csdn.net/qq_44962429/article/details/113604673
今日推荐