µ±Ç°Î»ÖãºÖ÷Ò³ > ²é¿´ÄÚÈÝ

³õ̽ Redis ¿Í»§¶Ë Lettuce£ºÕæÏ㣡

·¢²¼Ê±¼ä£º2021-07-12 00:00| ÓРλÅóÓѲ鿴

¼ò½é£ºÒ»¡¢Lettuce ÊÇɶ£¿ Ò»´Î¼¼ÊõÌÖÂÛ»áÉÏ£¬´ó¼Ò˵Æð Redis µÄ Java ¿Í»§¶ËÄļÒÇ¿£¬ÎÒµÚһʱ¼äºÁ²»ÓÌÔ¥µØº°³ö "Jedis, YES£¡" ¡°Jedis ¿ÉÊǹٷ½¿Í»§¶Ë£¬ÓÃÆðÀ´Ö±½ÓÊ¡Ê£¬¹«Ë¾Öмä¼þ¶¼ÓÃËü¡£³ýÁË Jedis ÍâÄѵÀ»¹Óеڶþ¸öÄÜ´òµÄ£¿¡±ÎÒÖ±½ÓÈÓ³öÍõÕ¨¡£ ¸Õѧ Spring¡­¡­

Ò»¡¢Lettuce ÊÇɶ£¿

Ò»´Î¼¼ÊõÌÖÂÛ»áÉÏ£¬´ó¼Ò˵Æð Redis µÄ Java ¿Í»§¶ËÄļÒÇ¿£¬ÎÒµÚһʱ¼äºÁ²»ÓÌÔ¥µØº°³ö "Jedis, YES£¡"

¡°Jedis ¿ÉÊǹٷ½¿Í»§¶Ë£¬ÓÃÆðÀ´Ö±½ÓÊ¡Ê£¬¹«Ë¾Öмä¼þ¶¼ÓÃËü¡£³ýÁË Jedis ÍâÄѵÀ»¹Óеڶþ¸öÄÜ´òµÄ£¿¡±ÎÒÖ±½ÓÈÓ³öÍõÕ¨¡£

¸Õѧ Spring µÄСÕÅÌýÁ˲»·þ£º¡°SpringDataRedis ¶¼Óà RedisTemplate£¡Jedis£¿²»´æÔڵġ£¡±

¡°×øÏ°ÉÐã¶ù£¬SpringDataRedis ¾ÍÊÇ»ùÓÚ Jedis ·â×°µÄ¡£¡±ÅÔ±ßÀî¸çßÈÁËÒ»¿Ú¸Õ¿ªµÄ¿ìÀÖË®£¬×ì½Ç΢΢ÉÏÑ¶³öһ˿²»Ð¼¡£

¡°ÏÖÔںܶ඼ÊÇÓà Lettuce ÁË£¬ÄãÃDz»»á²»ÖªµÀ°É£¿¡±ÀÏÍõÍÆÁËÍÆÑÛ¾µµ­µ­µØ˵µÀ£¬Ëæ¼´»º»º´ò¿ª¾µÆ¬ºóÄÇË«ÐÄÁéµÄ´°»§£¬Óùػ³µÄÑÛÉñ¸©ÊÓ×ÅÎÒÃǼ¸Ö»²Ë¼¦¡£

Lettuce£¿Éú²Ë£¿ÂúÍ·ÎíË®µÄÎҸϽô´ò¿ªÁË Redis ¹ÙÍøµÄ¿Í»§¶ËÁÐ±í¡£·¢ÏÖ Java ÓïÑÔÓÐÈý¸ö¹Ù·½ÍƼöµÄʵÏÖ£ºJedis¡¢LettuceºÍ?Redission¡£

(½ØͼÀ´Ô´£ºhttps://redis.io/clients#java)

Lettuce ÊÇʲô¿Í»§¶Ë£¿Ã»Ìý¹ý¡£µ«·¢ÏÖËüµÄ¹Ù·½½éÉÜ×£º

Advanced Redis client for thread-safe sync, async, and reactive usage. Supports Cluster, Sentinel, Pipelining, and codecs.

¸Ï½ô²é×Å×ֵ䷭ÒëÁËÏ£º

  • ¸ß¼¶¿Í»§¶Ë
  • Ḭ̈߳²È«
  • Ö§³Öͬ²½¡¢Òì²½ºÍ·´Ó¦Ê½ API
  • Ö§³Ö¼¯Èº¡¢ÉÚ±ø¡¢¹ÜµÀºÍ±à½âÂë

ÀÏÍõ°Ú°ÚÊÖʾÒâÎÒÊÕºÃ×ֵ䣬²»½ô²»Âý½éÉÜÆðÀ´¡£

1.1 ¸ß¼¶¿Í»§¶Ë

¡°Ê¦Ò¯£¬Äã¸ø·­Òë·­Ò룬ʲô£¨ßÙ¡ª¡ª£©½Ð×ö£¨ßÙ¡ª¡ª£©¸ß¼¶¿Í»§¶Ë£¿¡±

¡°¸ß¼¶¿Í»§¶ËÂ¸ß¼¶Â¾ÍÊÇ Advanced °¡£¡new һϾÍÄÜÓã¬Ê²Ã´ÊµÏÖϸ½Ú¶¼²»Óùܣ¬ÄÃÆðÒµÎñÂß¼­Ö±½Óͻͻ¡£¡±

1.2 Ḭ̈߳²È«

ÕâÊÇºÍ Jedis Ö÷Òª²»Í¬Ö®Ò»¡£

Jedis µÄÁ¬½ÓʵÀýÊÇÏ̲߳»°²È«µÄ£¬ÓÚÊÇÐèҪά»¤Ò»¸öÁ¬½Ó³Ø£¬Ã¿¸öÏß³ÌÐèҪʱ´ÓÁ¬½Ó³ØÈ¡³öÁ¬½ÓʵÀý£¬Íê³É²Ù×÷ºó»òÕßÓöµ½Òì³£¹é»¹ÊµÀý¡£µ±Á¬½ÓÊýËæ×ÅÒµÎñ²»¶ÏÉÏÉýʱ£¬¶ÔÎïÀíÁ¬½ÓµÄÏûºÄÒ²»á³ÉΪÐÔÄܺÍÎȶ¨ÐÔµÄDZÔÚ·çÏյ㡣

Lettuce ʹÓà Netty ×÷ΪͨÐŲã×é¼þ£¬ÆäÁ¬½ÓʵÀýÊÇḬ̈߳²È«µÄ£¬²¢ÇÒÔÚÌõ¼þ¾ß±¸Ê±¿É·ÃÎʲÙ×÷ϵͳԭÉúµ÷Óà epoll, kqueue µÈ»ñµÃÐÔÄÜÌáÉý¡£

ÎÒÃÇÖªµÀ Redis ·þÎñ¶ËʵÀýËäÈ»¿ÉÒÔͬʱÁ¬½Ó¶à¸ö¿Í»§¶ËÊÕ·¢ÃüÁµ«Ã¿¸öʵÀýÖ´ÐÐÃüÁîʱ¶¼Êǵ¥Ï̵߳ġ£

ÕâÒâζ×ÅÈç¹ûÓ¦ÓÿÉÒÔͨ¹ý¶àÏß³Ì+µ¥Á¬½Ó·½Ê½²Ù×÷ Redis£¬½«Äܹ»¾«¼ò Redis ·þÎñ¶ËµÄ×ÜÁ¬½ÓÊý£¬¶ø¶àÓ¦Óù²Ïíͬһ¸ö Redis ·þÎñ¶ËʱҲÄܹ»»ñµÃ¸üºÃµÄÎȶ¨ÐÔºÍÐÔÄÜ¡£¶ÔÓÚÓ¦ÓÃÀ´ËµÒ²¼õÉÙÁËά»¤¶à¸öÁ¬½ÓʵÀýµÄ×ÊÔ´ÏûºÄ¡£

1.3?Ö§³Öͬ²½¡¢Òì²½ºÍ·´Ó¦Ê½ API

Lettuce ´ÓÒ»¿ªÊ¼¾Í°´ÕÕ·Ç×èÈûʽ IO ½øÐÐÉè¼Æ£¬ÊÇÒ»¸ö´¿Òì²½¿Í»§¶Ë£¬¶ÔÒì²½ºÍ·´Ó¦Ê½ API µÄÖ§³Ö¶¼ºÜÈ«Ãæ¡£

¼´Ê¹ÊÇͬ²½ÃüÁµ×²ãµÄͨÐŹý³ÌÈÔÈ»ÊÇÒ첽ģÐÍ£¬Ö»ÊÇͨ¹ý×èÈûµ÷ÓÃÏß³ÌÀ´Ä£Äâ³öͬ²½Ð§¹û¶øÒÑ¡£

1.4 Ö§³Ö¼¯Èº¡¢ÉÚ±ø¡¢¹ÜµÀºÍ±à½âÂë

¡°ÕâЩÌØÐÔ¶¼ÊDZêÅ䣬Lettuce ¿ÉÊǸ߼¶¿Í»§¶Ë£¡¸ß¼¶£¬¶®Â𣿡±ÀÏÍõ˵µ½ÕâÀïÐ˷ܵØÓÃÊÖÖ¸µã×Å×ÀÃ棬µ«Ëƺõ²»Ïë¶à×ö½éÉÜ£¬ÎÒĬĬµØ¼ÇÏ´òËãºÃºÃѧϰһ·¬¡£

£¨ÔÚÏîĿʹÓùý³ÌÖУ¬pipeling »úÖÆÓÃÆðÀ´ºÍ Jedis Ïà±ÈÉÔ΢³éÏóÒѵ㣬ÏÂÎÄ»á¸ø³öÔÚʹÓùý³ÌÖÐÓöµ½µÄС¿ÓºÍ½â¾ö°ì·¨¡££©

1.5 ÔÚ Spring ÖеÄʹÓÃÇé¿ö

³ýÁË Redis ¹Ù·½½éÉÜ£¬ÎÒÃÇÒ²¿ÉÒÔ·¢ÏÖ Spring Data Redis ÔÚÉý¼¶µ½ 2.0 ʱ£¬½« Lettuce Éý¼¶µ½ÁË 5.0¡£Æäʵ Lettuce Ôç¾ÍÔÚ?SpringDataRedis 1.6?ʱ¾Í±»¹Ù·½¼¯³ÉÁË£»¶ø SpringSessionDataRedis ÔòÖ±½Ó½« Lettuce ×÷ΪĬÈÏ Redis ¿Í»§¶Ë£¬×ã¼ûÆä³ÉÊìºÍÎȶ¨¡£

Jedis ¹ãΪÈËÖªÉõÖÁÊÇÊÂʵÉϵıê×¼ Java ¿Í»§¶Ë£¨de-facto standard driver£©£¬ºÍËüÍƳöʱ¼äÔ磨1.0.0 °æ±¾ 2010 Äê 9 Ô£¬Lettuce 1.0.0 ÊÇ 2011 Äê 3 Ô£©¡¢API Ö±½ÓÒ×Óá¢¶Ô Redis ÐÂÌØÐÔÖ§³Ö×î¿ìµÈÌص㶼Ãܲ»¿É·Ö¡£

µ« Lettuce ×÷Ϊºó½ø£¬ÆäÓÅÊƺÍÒ×ÓÃÐÔÒ²»ñµÃÁË Spring µÈÉçÇøµÄÇàíù¡£ÏÂÃæ»á·ÖÏíÎÒÃÇÔÚÏîÄ¿Öм¯³É Lettuce ʱµÄ¾­Ñé×ܽᣬ¹©´ó¼Ò²Î¿¼¡£

¶þ¡¢Jedis ºÍ Lettuce ÓÐɶÖ÷ÒªÇø±ð£¿

˵ÁËÕâô¶à£¬Lettuce ºÍÀÏÅÆ¿Í»§¶Ë Jedis Ö÷Òª¶¼ÓÐÄÄЩÇø±ðÄØ£¿ÎÒÃÇ¿ÉÒÔ¿´ÏÂ?Spring Data Redis?°ïÖúÎĵµ¸ø³öµÄ¶Ô±È±í¸ñ£º

£¨½ØͼÀ´Ô´£ºhttps://docs.spring.io£©

×¢£ºÆäÖÐ X ±ê¼ÇµÄÊÇÖ§³Ö.

¾­¹ý±È½ÏÎÒÃÇ¿ÉÒÔ·¢ÏÖ£º

  • Jedis Ö§³ÖµÄ Lettuce ¶¼Ö§³Ö£»
  • Jedis ²»Ö§³ÖµÄ Lettuce Ò²Ö§³Ö£¡

Õâô¿´À´ Spring ÖÐÔ½À´Ô½¶àµØʹÓà Lettuce Ò²¾Í²»Ææ¹ÖÁË¡£

Èý¡¢Lettuce ³õÌåÑé

¹â˵²»Á·¼Ù°Ñʽ£¬¸ø´ó¼Ò·ÖÏíÎÒÃdz¢ÊÔ Lettuce ʱµÄÊÕ»ñ£¬ÓÈÆäÊÇÅúÁ¿ÃüÁ·Ö»¨Á˱Ƚ϶àµÄʱ¼ä²È¿Ó£¬ÏÂÎÄÏê½â¡£

3.1 ¿ìËÙ¿ªÊ¼

Èç¹û×î¼òµ¥µÄÀý×Ó¶¼ÁîÈ˷ѽ⣬ÄÇÕâ¸ö¿â¿Ï¶¨Á÷Ðв»ÆðÀ´¡£Lettuce µÄ¿ìËÙ¿ªÊ¼ÕæµÄ¹»¿ì£º

a. ÒýÈë maven ÒÀÀµ£¨ÆäËûÒÀÀµÀàËÆ£¬¾ßÌå¿É¼ûÎÄÄ©²Î¿¼×ÊÁÏ£©

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

b. ÌîÉÏ Redis µØÖ·£¬Á¬½Ó¡¢Ö´ÐС¢¹Ø±Õ¡£Perfect£¡

import io.lettuce.core.*;
 
// Syntax: redis://[password@]host[:port][/databaseNumber]
// Syntax: redis://[username:password@]host[:port][/databaseNumber]
RedisClient redisClient = RedisClient.create("redis://password@localhost:6379/0");
StatefulRedisConnection<String, String> connection = redisClient.connect();
RedisCommands<String, String> syncCommands = connection.sync();
 
syncCommands.set("key", "Hello, Redis!");
 
connection.close();
redisClient.shutdown();

3.2 Ö§³Ö¼¯ÈºÄ£Ê½Âð£¿Ö§³Ö£¡

Redis Cluster Êǹٷ½ÌṩµÄ Redis Sharding ·½°¸£¬´ó¼ÒÓ¦¸Ã·Ç³£ÊìϤ²»ÔÙ¶à½éÉÜ£¬¹Ù·½Îĵµ¿É²Î¿¼?Redis Cluster 101¡£

Lettuce Á¬½Ó Redis ¼¯Èº¶ÔÉÏÊö¿Í»§¶Ë´úÂëÒ»Ðл»Ò»Ï¼´¿É£º

// Syntax: redis://[password@]host[:port]
// Syntax: redis://[username:password@]host[:port]
RedisClusterClient redisClient = RedisClusterClient.create("redis://password@localhost:7379");

3.3 Ö§³Ö¸ß¿É¿¿Âð£¿Ö§³Ö£¡

Redis Sentinel Êǹٷ½ÌṩµÄ¸ß¿É¿¿·½°¸£¬Í¨¹ý Sentinel ¿ÉÒÔÔÚʵÀý¹ÊÕÏʱ×Ô¶¯Çл»µ½´Ó½Úµã¼ÌÐøÌṩ·þÎñ£¬¹Ù·½Îĵµ¿É²Î¿¼?Redis Sentinel Documentation¡£

ÈÔÈ»ÊÇÌæ»»¿Í»§¶ËµÄ´´½¨·½Ê½¾Í¿ÉÒÔÁË£º

// Syntax: redis-sentinel://[password@]host[:port][,host2[:port2]][/databaseNumber]#sentinelMasterId
RedisClient redisClient = RedisClient.create("redis-sentinel://localhost:26379,localhost:26380/0#mymaster");

3.4 Ö§³Ö¼¯ÈºÏ嵀 pipeline Âð£¿Ö§³Ö£¡

Jedis ËäÈ»ÓÐ pipeline ÃüÁµ«²»ÄÜÖ§³Ö Redis Cluster¡£Ò»°ã¶¼ÐèÒª×ÔÐй鲢¸÷¸ö key ËùÔÚµÄ slot ºÍʵÀýºóÔÙÅúÁ¿Ö´ÐÐ pipeline¡£

¹ÙÍø¶Ô¼¯ÈºÏ嵀 pipeline Ö§³Ö PR ½ØÖÁ±¾ÎÄд×÷ʱ£¨2021Äê2Ô£©ËÄÄê¹ýÈ¥ÁËÈÔȻδºÏÈ룬¿É¼û?Cluster pipelining¡£

Lettuce ËäÈ»ºÅ³ÆÖ§³Ö pipeling£¬µ«²¢Ã»ÓÐÖ±½Ó¿´µ½ pipeline ÕâÖÖ API£¬ÕâÊÇÔõô»ØÊ£¿

3.4.1 ʵÏÖ pipeline

ʹÓà AsyncCommands ºÍ flushCommands ʵÏÖ pipeline£¬¾­¹ýÔĶÁ¹Ù·½Îĵµ¿ÉÒÔÖªµÀ£¬Lettuce µÄͬ²½¡¢Òì²½ÃüÁîÆäʵ¶¼¹²Ïíͬһ¸öÁ¬½ÓʵÀý£¬µ×²ãʹÓà pipeline µÄÐÎʽÔÚ·¢ËÍ/½ÓÊÕÃüÁî¡£

Çø±ðÔÚÓÚ£º

  • connection.sync() ·½·¨»ñÈ¡µÄͬ²½ÃüÁî¶ÔÏó£¬Ã¿Ò»¸ö²Ù×÷¶¼»áÁ¢¿Ì½«ÃüÁîͨ¹ý TCP Á¬½Ó·¢ËͳöÈ¥£»
  • connection.async() »ñÈ¡µÄÒì²½ÃüÁî¶ÔÏó£¬Ö´ÐвÙ×÷ºóµÃµ½µÄÊÇ RedisFuture<?>£¬ÔÚÂú×ãÒ»¶¨Ìõ¼þµÄÇé¿öϲÅÅúÁ¿·¢ËÍ¡£

ÓÉ´ËÎÒÃÇ¿ÉÒÔͨ¹ýÒì²½ÃüÁî+ÊÖ¶¯ÅúÁ¿ÍÆË͵ķ½Ê½À´ÊµÏÖ pipeline£¬À´¿´¹Ù·½Ê¾Àý£º

StatefulRedisConnection<String, String> connection = client.connect();
RedisAsyncCommands<String, String> commands = connection.async();
 
// disable auto-flushing
commands.setAutoFlushCommands(false);
 
// perform a series of independent calls
List<RedisFuture<?>> futures = Lists.newArrayList();
for (int i = 0; i < iterations; i++) {
futures.add(commands.set("key-" + i, "value-" + i));
futures.add(commands.expire("key-" + i, 3600));
}
 
// write all commands to the transport layer
commands.flushCommands();
 
// synchronization example: Wait until all futures complete
boolean result = LettuceFutures.awaitAll(5, TimeUnit.SECONDS,
futures.toArray(new RedisFuture[futures.size()]));
 
// later
connection.close();

3.4.2 Õâô×öÓÐûÓÐÎÊÌ⣿

Õ§Ò»¿´ºÜÍêÃÀ£¬µ«ÆäʵÓаµ¿Ó£ºsetAutoFlushCommands(false)?ÉèÖú󣬻ᷢÏÖ sync() ·½·¨µ÷ÓõÄͬ²½ÃüÁ²»·µ»ØÁË£¡ÕâÊÇΪʲôÄØ£¿ÎÒÃÇÔÙ¿´¿´¹Ù·½Îĵµ£º

Lettuce is a non-blocking and asynchronous client. It provides a synchronous API to achieve a blocking behavior on a per-Thread basis to create await (synchronize) a command response..... As soon as the first request returns, the first Thread¡¯s program flow continues, while the second request is processed by Redis and comes back at a certain point in time

sync ºÍ async ÔڵײãʵÏÖÉ϶¼ÊÇÒ»ÑùµÄ£¬Ö»ÊÇ sync ͨ¹ý×èÈûµ÷ÓÃÏ̵߳ķ½Ê½Ä£ÄâÁËͬ²½²Ù×÷¡£²¢ÇÒ setAutoFlushCommands ͨ¹ýÔ´Âë¿ÉÒÔ·¢ÏÖ¾ÍÊÇ×÷ÓÃÔÚ connection ¶ÔÏóÉÏ£¬ÓÚÊǸòÙ×÷¶Ô sync ºÍ async ÃüÁî¶ÔÏó¶¼ÉúЧ¡£

ËùÒÔ£¬Ö»ÒªÄ³¸öÏß³ÌÖÐÉèÖÃÁË auto flush commands Ϊ false£¬¾Í»áÓ°Ïìµ½ËùÓÐʹÓøÃÁ¬½ÓʵÀýµÄÆäËûÏ̡߳£

/**
* An asynchronous and thread-safe API for a Redis connection.
*
* @param <K> Key type.
* @param <V> Value type.
* @author Will Glozer
* @author Mark Paluch
*/
public abstract class AbstractRedisAsyncCommands<K, V> implements RedisHashAsyncCommands<K, V>, RedisKeyAsyncCommands<K, V>,
RedisStringAsyncCommands<K, V>, RedisListAsyncCommands<K, V>, RedisSetAsyncCommands<K, V>,
RedisSortedSetAsyncCommands<K, V>, RedisScriptingAsyncCommands<K, V>, RedisServerAsyncCommands<K, V>,
RedisHLLAsyncCommands<K, V>, BaseRedisAsyncCommands<K, V>, RedisTransactionalAsyncCommands<K, V>,
RedisGeoAsyncCommands<K, V>, RedisClusterAsyncCommands<K, V> {
    @Override
    public void setAutoFlushCommands(boolean autoFlush) {
        connection.setAutoFlushCommands(autoFlush);
    }
}

¶ÔÓ¦µÄ£¬Èç¹û¶à¸öÏ̵߳÷ÓÃ?async()?»ñÈ¡Òì²½ÃüÁ£¬²¢ÔÚ×ÔÉíÒµÎñÂß¼­Íê³Éºóµ÷ÓÃ?flushCommands()£¬Äǽ«»áÇ¿ÐÐ flush ÆäËûÏ̻߳¹ÔÚ×·¼ÓµÄÒì²½ÃüÁԭ±¾Âß¼­ÉÏÊôÓÚÕûÅúµÄÃüÁ±»´òÉ¢³É¶à·Ý·¢ËÍ¡£

ËäÈ»¶ÔÓÚ½á¹ûµÄÕýÈ·ÐÔ²»Ó°Ï죬µ«Èç¹ûÒòΪÏß³ÌÏ໥ӰÏì´òÉ¢±Ë´ËµÄÃüÁî½øÐз¢ËÍ£¬Ôò¶ÔÐÔÄܵÄÌáÉý¾Í»áºÜ²»Îȶ¨¡£

×ÔÈ»ÎÒÃÇ»áÏëµ½£ºÃ¿¸öÅúÃüÁî´´½¨Ò»¸ö connection£¬È»ºó¡­¡­Õâ²»ºÍ Jedis Ò»ÑùÒ²ÊÇ¿¿Á¬½Ó³Øô£¿

»ØÏëÆðÀÏÍõ¾µÆ¬ºóÄÇ´©Í¸Áé»êµÄÄ¿¹â£¬ÎÒ´òËãÓ²×ÅͷƤÔÙÍÚ¾òһϡ£¹ûÈ»£¬ÔÙ´ÎÈÏÕæÔĶÁÎĵµºóÎÒ·¢ÏÖÁËÁíÍâÒ»¸öºÃ¶«Î÷£ºBatch Execution¡£

3.4.3 Batch Execution

¼ÈÈ» flushCommands »á¶Ô connection ²úÉúÈ«¾ÖÓ°Ï죬ÄÇ°Ñ flush ÏÞÖÆÔÚÏ̼߳¶±ð²»¾ÍÐÐÁË£¿ÎÒ´ÓÎĵµÖÐÕÒµ½ÁËʾÀý¹Ù·½Ê¾Àý¡£

»ØÏëÆðÇ°ÎÄ Lettuce ÊǸ߼¶¿Í»§¶Ë£¬¿´ÁËÎĵµºó·¢ÏÖȷʵ¸ß¼¶£¬Ö»ÐèÒª¶¨Òå½Ó¿Ú¾ÍÐÐÁË£¨ÈÃÈËÏëÆð MyBatis µÄ Mapper ½Ó¿Ú£©£¬ÏÂÃæÊÇÏîÄ¿ÖÐʹÓõÄÀý×Ó£º

/
/**
 * ¶¨Òå»áÓõ½µÄÅúÁ¿ÃüÁî
 */
@BatchSize(100)
public interface RedisBatchQuery extends Commands, BatchExecutor {
    RedisFuture<byte[]> get(byte[] key);
    RedisFuture<Set<byte[]>> smembers(byte[] key);
    RedisFuture<List<byte[]>> lrange(byte[] key, long start, long end);
    RedisFuture<Map<byte[], byte[]>> hgetall(byte[] key);
}

µ÷ÓÃʱÕâÑù²Ù×÷£º

// ´´½¨¿Í»§¶Ë
RedisClusterClient client = RedisClusterClient.create(DefaultClientResources.create(), "redis://" + address);
 
// service ÖгÖÓÐ factory ʵÀý£¬Ö»´´½¨Ò»´Î¡£µÚ¶þ¸ö²ÎÊý±íʾ key ºÍ value ʹÓà byte[] ±à½âÂë
RedisCommandFactory factory = new RedisCommandFactory(connect, Arrays.asList(ByteArrayCodec.INSTANCE, ByteArrayCodec.INSTANCE));
 
// ʹÓõĵط½£¬´´½¨Ò»¸ö²éѯʵÀý´úÀíÀàµ÷ÓÃÃüÁ×îºóË¢ÈëÃüÁî
List<RedisFuture<?>> futures = new ArrayList<>();
RedisBatchQuery batchQuery = factory.getCommands(RedisBatchQuery.class);
for (RedisMetaGroup redisMetaGroup : redisMetaGroups) {
    // ÒµÎñÂß¼­£¬Ñ­»·µ÷Óöà¸ö key ²¢½«½á¹û±£´æµ½ futures ½á¹ûÖÐ
    appendCommand(redisMetaGroup, futures, batchQuery);
}
 
// Òì²½ÃüÁîµ÷ÓÃÍê³ÉºóÖ´ÐÐ flush ÅúÁ¿Ö´ÐУ¬´ËʱÃüÁî²Å»á·¢Ë͸ø Redis ·þÎñ¶Ë
batchQuery.flush();

¾ÍÊÇÕâô¼òµ¥¡£

´ËʱÅúÁ¿µÄ¿ØÖƽ«ÔÚÏß³ÌÁ£¶ÈÉϽøÐУ¬²¢ÔÚµ÷Óà flush »ò´ïµ½ @BatchSize ÅäÖõĻº´æÃüÁîÊýÁ¿Ê±Ö´ÐÐÅúÁ¿²Ù×÷¡£¶ø¶ÔÓÚ connection ʵÀý£¬²»ÓÃÔÙÉèÖà auto flush commands£¬±£³ÖĬÈ쵀 true ¼´¿É£¬¶ÔÆäËûÏ̲߳»Ôì³ÉÓ°Ïì¡£

ps£ºÓÅÐã¡¢ÑϽ÷µÄÄã¿Ï¶¨»áÏëµ½£ºÈç¹ûµ¥ÃüÁîÖ´ÐкÄʱ³¤»òÕßË­·ÅÁ˸öÖîÈç BLPOP µÄÃüÁîµÄ»°£¬¿Ï¶¨»áÔì³ÉÓ°ÏìµÄ£¬Õâ¸ö»°Ìâ¹Ù·½ÎĵµÒ²ÓÐÉæ¼°£¬¿ÉÒÔ¿¼ÂÇʹÓÃÁ¬½Ó³ØÀ´´¦Àí¡£

3.5 »¹ÄÜÔÙ¸øÁ¦Ò»µãÂð£¿

Lettuce Ö§³ÖµÄµ±È»²»½ö½öÊÇÉÏÃæËù˵µÄ¼òµ¥¹¦ÄÜ£¬»¹ÓÐÕâЩҲֵµÃÒ»ÊÔ£º

3.5.1 ¶Áд·ÖÀë

ÎÒÃÇÖªµÀ Redis ʵÀýÊÇÖ§³ÖÖ÷´Ó²¿ÊðµÄ£¬´ÓʵÀýÒì²½µØ´ÓÖ÷ʵÀýͬ²½Êý¾Ý£¬²¢½èÖú Redis Sentinel ÔÚÖ÷ʵÀý¹ÊÕÏʱ½øÐÐÖ÷´ÓÇл»¡£

µ±Ó¦ÓöÔÊý¾ÝÒ»ÖÂÐÔ²»Ãô¸Ð¡¢ÓÖÐèÒª½Ï´óÍÌÍÂÁ¿Ê±£¬¿ÉÒÔ¿¼ÂÇÖ÷´Ó¶Áд·ÖÀ뷽ʽ¡£Lettuce ¿ÉÒÔÉèÖà StatefulRedisClusterConnection µÄ readFrom ÅäÖÃÀ´½øÐе÷Õû£º

3.5.2 ÅäÖÃ×Ô¶¯¸üм¯ÈºÍØÆË

µ±Ê¹Óà Redis Cluster ʱ£¬·þÎñ¶Ë·¢ÉúÁËÀ©ÈÝÔõô°ì£¿

Lettuce Ôç¾Í¿¼ÂǺÃÁË¡ª¡ªÍ¨¹ý RedisClusterClient#setOptions ·½·¨´«Èë ClusterClientOptions ¶ÔÏó¼´¿ÉÅäÖÃÏà¹Ø²ÎÊý£¨È«²¿ÅäÖüûÎÄÄ©²Î¿¼Á´½Ó£©¡£

ClusterClientOptions ÖеÄ?topologyRefreshOptions ³£¼ûÅäÖÃÈçÏ£º

3.5.3 Á¬½Ó³Ø

ËäÈ» Lettuce »ùÓÚḬ̈߳²È«µÄµ¥Á¬½ÓʵÀýÒѾ­¾ßÓзdz£ºÃµÄÐÔÄÜ£¬µ«Ò²²»ÅųýÓÐЩ´óÐÍÒµÎñÐèҪͨ¹ýÏ̳߳ØÀ´ÌáÉýÍÌÍÂÁ¿¡£ÁíÍâ¶ÔÓÚÊÂÎñÐÔ²Ù×÷ÊÇÓбØÒª¶ÀÕ¼Á¬½ÓµÄ¡£

Lettuce »ùÓÚ Apache Common-pool2 ×é¼þÌṩÁËÁ¬½Ó³ØµÄÄÜÁ¦£¨ÒÔÏÂÊǹٷ½ÌṩµÄ RedisCluster ¶ÔÓ¦µÄ¿Í»§¶ËÏ̳߳ØʹÓÃʾÀý£©£º

RedisClusterClient clusterClient = RedisClusterClient.create(RedisURI.create(host, port));
 
GenericObjectPool<StatefulRedisClusterConnection<String, String>> pool = ConnectionPoolSupport
               .createGenericObjectPool(() -> clusterClient.connect(), new GenericObjectPoolConfig());
 
// execute work
try (StatefulRedisClusterConnection<String, String> connection = pool.borrowObject()) {
    connection.sync().set("key", "value");
    connection.sync().blpop(10, "list");
}
 
// terminating
pool.close();
clusterClient.shutdown();

ÕâÀïÐèҪ˵Ã÷µÄÊÇ£ºcreateGenericObjectPool?´´½¨Á¬½Ó³ØĬÈÏÉèÖÃ?wrapConnections?²ÎÊýΪ true¡£´Ëʱ½è³öµÄ¶ÔÏó close ·½·¨½«Í¨¹ý¶¯Ì¬´úÀíµÄ·½Ê½ÖØÔØΪ¹é»¹Á¬½Ó£»ÈôÉèÖÃΪ false Ôò close ·½·¨»á¹Ø±ÕÁ¬½Ó¡£

Lettuce Ò²Ö§³ÖÒì²½µÄÁ¬½Ó³Ø£¨´ÓÁ¬½Ó³Ø»ñÈ¡Á¬½ÓΪÒì²½²Ù×÷£©£¬ÏêÇé¿É²Î¿¼ÎÄÄ©Á´½Ó¡£»¹ÓкܶàÌØÐÔ²»ÄÜÒ»Ò»Áо٣¬¶¼¿ÉÒÔÔÚ¹Ù·½ÎĵµÉÏÕÒµ½ËµÃ÷ºÍʾÀý£¬Ê®·ÖÖµµÃÒ»¶Á¡£

ËÄ¡¢Ê¹ÓÃ×ܽá

Lettuce Ïà½ÏÓÚJedis£¬Ê¹ÓÃÉϸü¼Ó·½±ã¿ì½Ý£¬³éÏó¶È¸ß¡£²¢ÇÒͨ¹ýḬ̈߳²È«µÄÁ¬½Ó½µµÍÁËϵͳÖеÄÁ¬½ÓÊýÁ¿£¬ÌáÉýÁËϵͳµÄÎȶ¨ÐÔ¡£

¶ÔÓڸ߼¶Íæ¼Ò£¬Lettuce Ò²ÌṩÁ˺ܶàÅäÖᢽӿڣ¬·½±ã¶ÔÐÔÄܽøÐÐÓÅ»¯ºÍʵÏÖÉî¶ÈÒµÎñ¶¨ÖƵij¡¾°¡£

ÁíÍâ²»µÃ²»ËµµÄÒ»µã£¬Lettuce µÄ¹Ù·½ÎĵµÐ´µÄ·Ç³£È«ÃæϸÖ£¬Ê®·ÖÄѵá£ÉçÇø±È½Ï»îÔ¾£¬Commiter »á»ý¼«»Ø´ð¸÷Àà issue£¬ÕâʹµÃºÜ¶àÒÉÎʶ¼¿ÉÒÔ×ÔÖú½â¾ö¡£

Ïà±È֮ϣ¬Jedis µÄÎĵµ¡¢Î¬»¤¸üÐÂËٶȾͱȽÏÂýÁË¡£JedisCluster pipeline µÄ?PR?ÖÁ½ñ£¨2021Äê2Ô£©ËÄÄê¹ýÈ¥»¹Î´ºÏÈë¡£

²Î¿¼×ÊÁÏ

ÆäÖÐÁ½¸ö GitHub µÄ issue º¬½ðÁ¿ºÜ¸ß£¬Ç¿ÁÒÍƼöÒ»¶Á£¡

1.Lettuce ¿ìËÙ¿ªÊ¼£ºhttps://lettuce.io

2.Redis Java Clients

3.Lettuce ¹ÙÍø£ºhttps://lettuce.io

4.SpringDataRedis?²Î¿¼Îĵµ

5.Question about pipelining

6.Why is Lettuce the default Redis client used in Spring Session Redis

7.Cluster-specific options£ºhttps://lettuce.io

8.Lettuce Á¬½Ó³Ø

9.¿Í»§¶ËÅäÖãºhttps://lettuce.io/core/release

10.SSLÅäÖãºhttps://lettuce.io

×÷Õߣºvivo»¥ÁªÍøÊý¾ÝÖÇÄÜÍŶÓ-Li Haoxuan

±¾ÎÄת×ÔÍøÂ磬°æȨ¹éÔ­×÷ÕßËùÓУ¬Ô­ÎÄÁ´½Ó£ºhttps://segmentfault.com/a/1190000040331000
±¾Õ¾²¿·ÖÄÚÈÝתÔØÓÚÍøÂ磬°æȨ¹éÔ­×÷ÕßËùÓУ¬×ªÔØ֮ĿµÄÔÚÓÚ´«²¥¸ü¶àÓÅÐã¼¼ÊõÄÚÈÝ£¬ÈçÓÐÇÖȨÇëÁªÏµQQ/΢ÐÅ£º153890879ɾ³ý£¬Ð»Ð»£¡

ÍƼöͼÎÄ

  • ÖÜÅÅÐÐ
  • ÔÂÅÅÐÐ
  • ×ÜÅÅÐÐ

Ëæ»úÍƼö