Heim  >  Artikel  >  Datenbank  >  So verwenden Sie Salat in Redis

So verwenden Sie Salat in Redis

WBOY
WBOYnach vorne
2023-05-28 21:51:241648Durchsuche

1. Zusammenfassung

Lettuce ist neben Jedis einer der beliebtesten Clients für Redis.

Im Vergleich zu den alten Jedis ist Lettuce nicht nur reich an Funktionen, sondern bietet auch viele neue Funktionen wie asynchrone Operationen, reaktive Programmierung usw. und löst auch das Problem Thread-Unsicherheitsproblem in Jedis-Frage.

2. Salat

2.1. Grundlegende Verwendung

Erstellen Sie zunächst ein Maven-Projekt und führen Sie den lettuce-core ein Paket, Sie können es verwenden. lettuce-core包,就可以使用了。

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

使用 lettuce 连接 redis,测试是否能正常联通!

public class LettuceMain {

    public static void main(String[] args) {
        RedisURI redisUri = RedisURI.builder()
                .withHost("127.0.0.1")
                .withPort(6379)
                .withPassword("111111")
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        RedisClient redisClient = RedisClient.create(redisUri);
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        RedisCommands<String, String> commands = connection.sync();
        System.out.println(commands.ping());
        connection.close();
        redisClient.shutdown();
    }
}

2.2、同步操作

基本上只要是 Jedis 支持的同步命令操作,Lettuce 都支持。

下面,我们以同步操作字符串为例,Lettuce 的 api 操作如下!

public class LettuceSyncMain {

    public static void main(String[] args) {
        RedisURI redisUri = RedisURI.builder()
                .withHost("127.0.0.1").withPort(6379).withPassword("111111")
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        RedisClient redisClient = RedisClient.create(redisUri);
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        //获取同步操作命令工具
        RedisCommands<String, String> commands = connection.sync();

        System.out.println("清空数据:"+commands.flushdb());
        System.out.println("判断某个键是否存在:"+commands.exists("username"));
        System.out.println("新增<&#39;username&#39;,&#39;xmr&#39;>的键值对:"+commands.set("username", "xmr"));
        System.out.println("新增<&#39;password&#39;,&#39;password&#39;>的键值对:"+commands.set("password", "123"));
        System.out.println("获取<&#39;password&#39;>键的值:"+commands.get("password"));
        System.out.println("系统中所有的键如下:" + commands.keys("*"));
        System.out.println("删除键password:"+commands.del("password"));
        System.out.println("判断键password是否存在:"+commands.exists("password"));
        System.out.println("设置键username的过期时间为5s:"+commands.expire("username", 5L));
        System.out.println("查看键username的剩余生存时间:"+commands.ttl("username"));
        System.out.println("移除键username的生存时间:"+commands.persist("username"));
        System.out.println("查看键username的剩余生存时间:"+commands.ttl("username"));
        System.out.println("查看键username所存储的值的类型:"+commands.type("username"));

        connection.close();
        redisClient.shutdown();
    }
}

2.3、异步操作

除此之外,Lettuce 还支持异步操作,将上面的操作改成异步处理,结果如下!

public class LettuceASyncMain {

    public static void main(String[] args) throws Exception {
        RedisURI redisUri = RedisURI.builder()
                .withHost("127.0.0.1").withPort(6379).withPassword("111111")
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        RedisClient redisClient = RedisClient.create(redisUri);
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        //获取异步操作命令工具
        RedisAsyncCommands<String, String> commands = connection.async();

        System.out.println("清空数据:"+commands.flushdb().get());
        System.out.println("判断某个键是否存在:"+commands.exists("username").get());
        System.out.println("新增<&#39;username&#39;,&#39;xmr&#39;>的键值对:"+commands.set("username", "xmr").get());
        System.out.println("新增<&#39;password&#39;,&#39;password&#39;>的键值对:"+commands.set("password", "123").get());
        System.out.println("获取<&#39;password&#39;>键的值:"+commands.get("password").get());
        System.out.println("系统中所有的键如下:" + commands.keys("*").get());
        System.out.println("删除键password:"+commands.del("password").get());
        System.out.println("判断键password是否存在:"+commands.exists("password").get());
        System.out.println("设置键username的过期时间为5s:"+commands.expire("username", 5L).get());
        System.out.println("查看键username的剩余生存时间:"+commands.ttl("username").get());
        System.out.println("移除键username的生存时间:"+commands.persist("username").get());
        System.out.println("查看键username的剩余生存时间:"+commands.ttl("username").get());
        System.out.println("查看键username所存储的值的类型:"+commands.type("username").get());

        connection.close();
        redisClient.shutdown();
    }
}

2.4、响应式编程

Lettuce 除了支持异步编程以外,还支持响应式编程,Lettuce 引入的响应式编程框架是Project Reactor

public class LettuceMain {

    public static void main(String[] args) throws Exception {
        RedisURI redisUri = RedisURI.builder()
                .withHost("127.0.0.1").withPort(6379).withPassword("111111")
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        RedisClient redisClient = RedisClient.create(redisUri);
        StatefulRedisConnection<String, String> connection = redisClient.connect();
        //获取响应式API操作命令工具
        RedisReactiveCommands<String, String> commands = connection.reactive();

        Mono<String> setc = commands.set("name", "mayun");
        System.out.println(setc.block());
        Mono<String> getc = commands.get("name");
        getc.subscribe(System.out::println);
        Flux<String> keys = commands.keys("*");
        keys.subscribe(System.out::println);

        //开启一个事务,先把count设置为1,再将count自增1
        commands.multi().doOnSuccess(r -> {
            commands.set("count", "1").doOnNext(value -> System.out.println("count1:" +  value)).subscribe();
            commands.incr("count").doOnNext(value -> System.out.println("count2:" +  value)).subscribe();
        }).flatMap(s -> commands.exec())
                .doOnNext(transactionResult -> System.out.println("transactionResult:" + transactionResult.wasDiscarded())).subscribe();

        Thread.sleep(1000 * 5);
        connection.close();
        redisClient.shutdown();
    }
}

Verwenden Sie Salat, um eine Verbindung zu Redis herzustellen und zu testen, ob die Verbindung normal sein kann!

public class LettuceReactiveMain1 {

    public static void main(String[] args) throws Exception {
        RedisURI redisUri = RedisURI.builder()
                .withHost("127.0.0.1").withPort(6379).withPassword("111111")
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        RedisClient redisClient = RedisClient.create(redisUri);
        //获取发布订阅操作命令工具
        StatefulRedisPubSubConnection<String, String> pubsubConn = redisClient.connectPubSub();
        pubsubConn.addListener(new RedisPubSubListener<String, String>() {
            @Override
            public void unsubscribed(String channel, long count) {
                System.out.println("[unsubscribed]" + channel);
            }
            @Override
            public void subscribed(String channel, long count) {
                System.out.println("[subscribed]" + channel);
            }
            @Override
            public void punsubscribed(String pattern, long count) {
                System.out.println("[punsubscribed]" + pattern);
            }
            @Override
            public void psubscribed(String pattern, long count) {
                System.out.println("[psubscribed]" + pattern);
            }
            @Override
            public void message(String pattern, String channel, String message) {
                System.out.println("[message]" + pattern + " -> " + channel + " -> " + message);
            }
            @Override
            public void message(String channel, String message) {
                System.out.println("[message]" + channel + " -> " + message);
            }
        });
        RedisPubSubAsyncCommands<String, String> pubsubCmd = pubsubConn.async();
        pubsubCmd.psubscribe("CH");
        pubsubCmd.psubscribe("CH2");
        pubsubCmd.unsubscribe("CH");

        Thread.sleep(100 * 5);
        pubsubConn.close();
        redisClient.shutdown();
    }
}

2.2. Synchroner Betrieb

Grundsätzlich unterstützt Lettuce alle von Jedis unterstützten synchronen Befehlsoperationen.

Im Folgenden nehmen wir die synchrone Operation von Strings als Beispiel. Die API-Operation von Lettuce ist wie folgt!

public class LettuceMain {

    public static void main(String[] args) throws Exception {
        ClientResources resources = DefaultClientResources.builder()
                .ioThreadPoolSize(4) //I/O线程数
                .computationThreadPoolSize(4) //任务线程数
                .build();
        RedisURI redisUri = RedisURI.builder()
                .withHost("127.0.0.1").withPort(6379).withPassword("111111")
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        ClientOptions options = ClientOptions.builder()
                .autoReconnect(true)//是否自动重连
                .pingBeforeActivateConnection(true)//连接激活之前是否执行PING命令
                .build();
        RedisClient client = RedisClient.create(resources, redisUri);
        client.setOptions(options);
        StatefulRedisConnection<String, String> connection = client.connect();
        RedisCommands<String, String> commands = connection.sync();
        commands.set("name", "关羽");
        System.out.println(commands.get("name"));

        connection.close();
        client.shutdown();
        resources.shutdown();
    }
}

2.3. Asynchroner Betrieb

Darüber hinaus unterstützt Lettuce auch den asynchronen Betrieb. Die Ergebnisse sind wie folgt!

public class LettuceMain {

    public static void main(String[] args) throws Exception {
        ClientResources resources = DefaultClientResources.builder()
                .ioThreadPoolSize(4) //I/O线程数
                .computationThreadPoolSize(4) //任务线程数
                .build();
        RedisURI redisUri = RedisURI.builder()
                .withHost("127.0.0.1").withPort(6379).withPassword("111111")
                .withTimeout(Duration.of(10, ChronoUnit.SECONDS))
                .build();
        ClusterClientOptions options = ClusterClientOptions.builder()
                .autoReconnect(true)//是否自动重连
                .pingBeforeActivateConnection(true)//连接激活之前是否执行PING命令
                .validateClusterNodeMembership(true)//是否校验集群节点的成员关系
                .build();
        RedisClusterClient client = RedisClusterClient.create(resources, redisUri);
        client.setOptions(options);
        StatefulRedisClusterConnection<String, String> connection = client.connect();
        RedisAdvancedClusterCommands<String, String> commands = connection.sync();
        commands.set("name", "张飞");
        System.out.println(commands.get("name"));

        connection.close();
        client.shutdown();
        resources.shutdown();
    }
}

2.4, Reaktive Programmierung

Zusätzlich zur Unterstützung der asynchronen Programmierung unterstützt Lettuce auch das von Lettuce eingeführte reaktive Programmier-Framework Project Reactor > Wenn Sie keine Erfahrung mit reaktiver Programmierung haben, können Sie sich zunächst selbst damit vertraut machen. <h4></h4>Reaktive Programmieranwendungsfälle sind wie folgt: <p><pre class="brush:java;">public class LettuceMain { public static void main(String[] args) throws Exception { RedisURI redisUri = RedisURI.builder() .withHost(&quot;127.0.0.1&quot;) .withPort(6379) .withPassword(&quot;111111&quot;) .withTimeout(Duration.of(10, ChronoUnit.SECONDS)) .build(); RedisClient client = RedisClient.create(redisUri); //连接池配置 GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); poolConfig.setMaxIdle(2); GenericObjectPool&lt;StatefulRedisConnection&lt;String, String&gt;&gt; pool = ConnectionPoolSupport.createGenericObjectPool(client::connect, poolConfig); StatefulRedisConnection&lt;String, String&gt; connection = pool.borrowObject(); RedisCommands&lt;String, String&gt; commands = connection.sync(); commands.set(&quot;name&quot;, &quot;张飞&quot;); System.out.println(commands.get(&quot;name&quot;)); connection.close(); pool.close(); client.shutdown(); } }</pre></p>2.5, Veröffentlichung und Abonnement <p></p>Lettuce unterstützt auch die Veröffentlichung und das Abonnement von Redis-Nachrichten sowie spezifische Implementierungsfälle Wie folgt: <h4><pre class="brush:java;">public class LettuceMain { public static void main(String[] args) throws Exception { //这里只需要配置一个节点的连接信息,不一定需要是主节点的信息,从节点也可以;可以自动发现主从节点 RedisURI uri = RedisURI.builder().withHost(&quot;192.168.31.111&quot;).withPort(6379).withPassword(&quot;123456&quot;).build(); RedisClient client = RedisClient.create(uri); StatefulRedisMasterReplicaConnection&lt;String, String&gt; connection = MasterReplica.connect(client, StringCodec.UTF8, uri); //从节点读取数据 connection.setReadFrom(ReadFrom.REPLICA); RedisCommands&lt;String, String&gt; commands = connection.sync(); commands.set(&quot;name&quot;, &quot;张飞&quot;); System.out.println(commands.get(&quot;name&quot;)); connection.close(); client.shutdown(); } }</pre></h4>2.6. Client-Ressourcen- und Parameterkonfiguration <p></p>Lettuce Das Kommunikations-Framework des Clients integriert die nicht blockierenden E/A-Vorgänge, Client-Ressourceneinstellungen und die Leistung, Parallelität und das Ereignis von Lettuce Wenn Sie mit der Konfiguration von Client-Parametern nicht besonders vertraut sind, ist es nicht empfehlenswert, die Standardwerte ohne Erfahrung intuitiv zu ändern und einfach die Standardkonfiguration beizubehalten. <p></p>In einer Nicht-Cluster-Umgebung lautet der spezifische Konfigurationsfall wie folgt: <p><pre class="brush:java;">public class LettuceMain { public static void main(String[] args) throws Exception { //集群节点 List&lt;RedisURI&gt; uris = new ArrayList(); uris.add(RedisURI.builder().withHost(&quot;192.168.31.111&quot;).withPort(6379).withPassword(&quot;111111&quot;).build()); uris.add(RedisURI.builder().withHost(&quot;192.168.31.112&quot;).withPort(6379).withPassword(&quot;111111&quot;).build()); uris.add(RedisURI.builder().withHost(&quot;192.168.31.113&quot;).withPort(6379).withPassword(&quot;111111&quot;).build()); RedisClient client = RedisClient.create(); StatefulRedisMasterReplicaConnection&lt;String, String&gt; connection = MasterReplica.connect(client, StringCodec.UTF8, uris); //从节点读取数据 connection.setReadFrom(ReadFrom.REPLICA); RedisCommands&lt;String, String&gt; commands = connection.sync(); commands.set(&quot;name&quot;, &quot;张飞&quot;); System.out.println(commands.get(&quot;name&quot;)); connection.close(); client.shutdown(); } }</pre></p> In einer Cluster-Umgebung lautet der spezifische Konfigurationsfall wie folgt: <h4><pre class="brush:java;">public class LettuceMain { public static void main(String[] args) throws Exception { //集群节点 List&lt;RedisURI&gt; uris = new ArrayList(); uris.add(RedisURI.builder().withSentinel(&quot;192.168.31.111&quot;, 26379).withSentinelMasterId(&quot;mymaster&quot;).withPassword(&quot;123456&quot;).build()); uris.add(RedisURI.builder().withSentinel(&quot;192.168.31.112&quot;, 26379).withSentinelMasterId(&quot;mymaster&quot;).withPassword(&quot;123456&quot;).build()); uris.add(RedisURI.builder().withSentinel(&quot;192.168.31.113&quot;, 26379).withSentinelMasterId(&quot;mymaster&quot;).withPassword(&quot;123456&quot;).build()); RedisClient client = RedisClient.create(); StatefulRedisMasterReplicaConnection&lt;String, String&gt; connection = MasterReplica.connect(client, StringCodec.UTF8, uris); //从节点读取数据 connection.setReadFrom(ReadFrom.REPLICA); RedisCommands&lt;String, String&gt; commands = connection.sync(); commands.set(&quot;name&quot;, &quot;赵云&quot;); System.out.println(commands.get(&quot;name&quot;)); connection.close(); client.shutdown(); } }</pre> </h4>2.7, Thread-Pool-Konfiguration <p></p>Die Lettuce-Verbindung ist threadsicher, sodass eine Verbindung von mehreren Threads gemeinsam genutzt werden kann. Gleichzeitig werden Salatverbindungen automatisch wieder verbunden. Die Verwendung einer einzelnen Verbindung kann grundsätzlich Geschäftsanforderungen erfüllen. In den meisten Fällen ist es nicht erforderlich, einen Verbindungspool zu konfigurieren, und mehrere Verbindungen verbessern die Leistung des Vorgangs nicht. <h4></h4>Aber in einigen speziellen Szenarien, wie z. B. Transaktionsvorgängen, wäre die Verwendung eines Verbindungspools eine bessere Lösung. Wie konfiguriert man den Thread-Pool? <p><pre class="brush:java;">public class LettuceReactiveMain4 { public static void main(String[] args) throws Exception { Set&lt;RedisURI&gt; uris = new HashSet&lt;&gt;(); uris.add(RedisURI.builder().withHost(&quot;192.168.31.111&quot;).withPort(7000).withPassword(&quot;123456&quot;).build()); uris.add(RedisURI.builder().withHost(&quot;192.168.31.112&quot;).withPort(7000).withPassword(&quot;123456&quot;).build()); uris.add(RedisURI.builder().withHost(&quot;192.168.31.113&quot;).withPort(7000).withPassword(&quot;123456&quot;).build()); uris.add(RedisURI.builder().withHost(&quot;192.168.31.114&quot;).withPort(7000).withPassword(&quot;123456&quot;).build()); uris.add(RedisURI.builder().withHost(&quot;192.168.31.115&quot;).withPort(7000).withPassword(&quot;123456&quot;).build()); uris.add(RedisURI.builder().withHost(&quot;192.168.31.116&quot;).withPort(7001).withPassword(&quot;123456&quot;).build()); RedisClusterClient client = RedisClusterClient.create(uris); StatefulRedisClusterConnection&lt;String, String&gt; connection = client.connect(); RedisAdvancedClusterCommands&lt;String, String&gt; commands = connection.sync(); commands.set(&quot;name&quot;, &quot;关羽&quot;); System.out.println(commands.get(&quot;name&quot;)); //选择从节点,只读 NodeSelection&lt;String, String&gt; replicas = commands.replicas(); NodeSelectionCommands&lt;String, String&gt; nodeSelectionCommands = replicas.commands(); Executions&lt;List&lt;String&gt;&gt; keys = nodeSelectionCommands.keys(&quot;*&quot;); keys.forEach(key -&gt; System.out.println(key)); connection.close(); client.shutdown(); } }</pre></p>2.8. Master-Slave-Modus-Konfiguration #🎜🎜##🎜🎜#redis verwendet im Allgemeinen den Master-Slave-Replikationsmodus, um eine Hochverfügbarkeitsarchitektur aufzubauen Mehrere Slave-Knoten synchronisieren automatisch die neuesten Daten vom Master-Knoten. #🎜🎜##🎜🎜#Lettuce unterstützt das automatische Erkennen von Knoteninformationen im Master-Slave-Modus und das anschließende lokale Speichern. Die spezifische Konfiguration ist wie folgt: #🎜🎜#rrreee#🎜🎜# Natürlich können wir die auch manuell festlegen Zu ladender Cluster-Knoten, wie detailliert beschrieben. Die Konfiguration lautet wie folgt: #🎜🎜#rrreee#🎜🎜#2.9, Sentinel-Modus-Konfiguration#🎜🎜##🎜🎜# Der Sentinel-Modus ist auch ein Highlight von Redis, um eine hohe Serviceverfügbarkeit zu erreichen Die spezifische Konfiguration wird wie folgt implementiert: #🎜🎜#rrreee# 🎜🎜#2.10, Konfiguration des Cluster-Cluster-Modus#🎜🎜##🎜🎜#Der Cluster-Cluster-Modus ist ein später eingeführtes Hochverfügbarkeitsarchitekturmodell, das hauptsächlich Sharding zum Speichern von Daten verwendet . Die spezifische Konfiguration ist wie folgt: #🎜🎜 #rrreee

Das obige ist der detaillierte Inhalt vonSo verwenden Sie Salat in Redis. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen