Redis7——基礎篇(八)

?前言:此篇文章系本人學習過程中記錄下來的筆記,里面難免會有不少欠缺的地方,誠心期待大家多多給予指教。

基礎篇:

  1. Redis(一)
  2. Redis(二)
  3. Redis(三)
  4. Redis(四)
  5. Redis(五)
  6. Redis(六)
  7. Redis(七)

接上期內容:上期完成了Redis集群的學習。下面開始學習Java集成Redis,話不多說,直接發車。


一、Java連接Redis的四種方式

(一)、底層客戶端庫

1、Jedis

1.1、定義

Jedis是Redis官方推薦的Java客戶端,它提供了一套簡潔易用的 API,用于與Redis 進行交互。Jedis支持同步、異步和管道操作,能夠滿足不同場景下的需求。


1.2、優劣勢

優勢:

  • 使用簡單,學習成本低,對初學者友好。
  • 同步阻塞 I/O,在單線程環境下使用方便。
  • 與 Redis的命令對應性強,容易上手

劣勢:

  • 在高并發場景下,由于同步阻塞 I/O 的特性,性能會受到一定影響
  • 多線程環境下,需要手動管理連接池,增加了開發復雜度

2、Lettuce

2.1、定義

Lettuce是一個基于Netty的可伸縮線程安全的Redis客戶端,它支持同步、異步和響應式編程模型。Lettuce的設計目標是提供高性能和可擴展性,適用于各種復雜的應用場景。


2.2、優劣勢

優勢:

  • 基于Netty實現,支持異步 I/O,在高并發場景下性能表現出色
  • 線程安全,無需手動管理連接池。
  • 支持多種編程模型,靈活性高

劣勢:

  • 相比Jedis,學習成本較高
  • API相對復雜,對于簡單場景可能顯得過于繁瑣。


(二)、上層框架封裝

1、RedisTemplate

1.1、定義

RedisTemplate是Spring Data Redis 提供的一個高級封裝,它簡化了Java與Redis的交互操作。RedisTemplate提供了豐富的方法,支持各種數據結構的操作,并且可以方便地進行事務管理和序列化配置。


1.2、優劣勢

優勢:

  • 與Spring 框架無縫集成,使用方便
  • 對各種數據結構的操作進行了封裝,代碼簡潔
  • 支持事務管理和序列化配置,提高了應用的靈活性和可維護性

劣勢:

  • 依賴Spring框架,如果項目中沒有使用 Spring,引入RedisTemplate會增加項目的復雜度
  • 相比底層客戶端庫,性能上可能會有一定損耗

2、Redisson

2.1、定義

Redisson是一個在Redis的基礎上實現的Java駐內存數據網格(In-Memory Data Grid)。它不僅提供了一系列的分布式的Java常用對象,還提供了許多分布式服務,如分布式鎖、分布式集合、分布式對象等,極大地簡化了分布式系統的開發。


2.2、優劣勢

優勢:

  • 提供了豐富的分布式服務,開箱即用,像分布式鎖、分布式集合等,非常適合構建分布式系統
  • 對Redis功能進行了高度抽象和擴展,使用起來更加便捷。
  • 支持多種序列化方式,兼容性好

劣勢:

  • 相比直接使用 Redis 客戶端,增加了一定的學習成本
  • 由于其功能豐富,依賴的包可能較多,在一些對依賴大小敏感的場景下不太適用。

二、實操

(一)、集成Jedis

1、新建項目

新建步驟略。最終效果圖:

2、導入依賴

        <!--jedis--><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>5.2.0</version></dependency>

3、編寫方法

3.1、連接redis單機
public class JedisDemoTest {public static void main(String[] args) {Jedis jedis = new Jedis("192.168.112.129", 6379);jedis.auth("root");jedis.set("k1", "你好jedis");System.out.println(jedis.get("k1"));//keySet<String> keys = jedis.keys("*");for (String key : keys) {System.out.println(key);}System.out.println("jedis.exists====>" + jedis.exists("k2"));System.out.println(jedis.ttl("k1"));//StringSystem.out.println(jedis.get("k1"));jedis.set("k4", "k4_redis");System.out.println("----------------------------------------");jedis.mset("str1", "v1", "str2", "v2", "str3", "v3");System.out.println(jedis.mget("str1", "str2", "str3"));//listSystem.out.println("----------------------------------------");jedis.lpush("myList", "v1", "v2", "v3", "v4", "v5");List<String> list = jedis.lrange("myList", 0, -1);for (String element : list) {System.out.println(element);}//setjedis.sadd("orders", "jd001");jedis.sadd("orders", "jd002");jedis.sadd("orders", "jd003");Set<String> set1 = jedis.smembers("orders");for (String string : set1) {System.out.println(string);}jedis.srem("orders", "jd002");System.out.println(jedis.smembers("orders").size());//hashjedis.hset("hash1", "userName", "lisi");System.out.println(jedis.hget("hash1", "userName"));Map<String, String> map = new HashMap<>();map.put("telephone", "138xxxxxxxx");map.put("address", "fatigue");map.put("email", "sxxxx@qq.com");//jedis.hmset("hash2", map);List<String> result = jedis.hmget("hash2", "telphone", "email");for (String element : result) {System.out.println(element);}//zSetjedis.zadd("zSet01", 60d, "v1");jedis.zadd("zSet01", 70d, "v2");jedis.zadd("zSet01", 80d, "v3");jedis.zadd("zSet01", 90d, "v4");List<String> zSet01 = jedis.zrange("zSet01", 0, -1);zSet01.forEach(System.out::println);// 關閉連接jedis.close();}
}

3.2、連接redis集群
public class JedisColonyDemoTest {public static void main(String[] args) {// 添加主節點HashSet<HostAndPort> jedisClusterNodes = new HashSet<>();jedisClusterNodes.add(new HostAndPort("192.168.112.129", 6379));jedisClusterNodes.add(new HostAndPort("192.168.112.130", 6381));jedisClusterNodes.add(new HostAndPort("192.168.112.129", 6380));// 連接redis集群JedisCluster cluster = new JedisCluster(jedisClusterNodes,"default","root");// 清除單機Redis設置的key// 如果用Jedis連接Redis集群模式下,// flushAll這類全局操作不能直接使用,在集群模式下對于一些全局操作命令(如 KEYS)的處理不夠完善,// 沒有內置的邏輯來處理 KEYS 命令在集群環境下的復雜性。for (HostAndPort node : jedisClusterNodes) {try (Jedis jedis = new Jedis(node.getHost(), node.getPort())) {jedis.auth("root");// 對每個節點執行 flushDB 命令jedis.flushDB();System.out.println("Flushed database on node: " + node);}}cluster.set("k1", "你好redis集群");System.out.println(cluster.get("k1"));System.out.println("cluster.exists====>" + cluster.exists("k2"));System.out.println(cluster.ttl("k1"));//StringSystem.out.println(cluster.get("k1"));cluster.set("k4", "k4_redis");System.out.println("----------------------------------------");cluster.mset("str1{x}", "v1", "str2{x}", "v2", "str3{x}", "v3");System.out.println(cluster.mget("str1{x}", "str2{x}", "str3{x}"));//listSystem.out.println("----------------------------------------");cluster.lpush("myList", "v1", "v2", "v3", "v4", "v5");List<String> list = cluster.lrange("myList", 0, -1);for (String element : list) {System.out.println(element);}//setcluster.sadd("orders", "jd001");cluster.sadd("orders", "jd002");cluster.sadd("orders", "jd003");Set<String> set1 = cluster.smembers("orders");for (String string : set1) {System.out.println(string);}cluster.srem("orders", "jd002");System.out.println(cluster.smembers("orders").size());//hashcluster.hset("hash1", "userName", "lisi");System.out.println(cluster.hget("hash1", "userName"));Map<String, String> map = new HashMap<>();map.put("telephone", "138xxxxxxxx");map.put("address", "fatigue");map.put("email", "sxxxx@qq.com");//cluster.hmset("hash2", map);List<String> result = cluster.hmget("hash2", "telphone", "email");for (String element : result) {System.out.println(element);}//zSetcluster.zadd("zSet01", 60d, "v1");cluster.zadd("zSet01", 70d, "v2");cluster.zadd("zSet01", 80d, "v3");cluster.zadd("zSet01", 90d, "v4");List<String> zSet01 = cluster.zrange("zSet01", 0, -1);zSet01.forEach(System.out::println);cluster.close();}
}

4、測試用例?

4.1、單機測試結果

?直接main方法啟動,

redis客戶端:


4.2、redis集群測試結果

控制臺輸入:

redis客戶端:


(二)、集成Lettuce

1、導入依賴

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

?*注意:如果你的Springboot版本為3.4.3,那么導入這個依賴后,可能需要清除IDEA緩存,不然一直無法new RedisURI類。刷新過maven也沒用,只有清除緩存重啟后才成功,就很奇怪( ╯□╰ )。


2、編寫方法

2.1、連接Redis單機
public class LettuceDemoTest {public static void main(String[] args) {// 構建 RedisURI 對象RedisURI uri = RedisURI.builder(RedisURI.create("redis://192.168.112.129")).withPort(6379).withAuthentication("default", "root").withDatabase(0).build();// 創建連接客戶端RedisClient client = RedisClient.create(uri);StatefulRedisConnection<String, String> conn = client.connect();// 操作命令apiRedisCommands<String, String> commands = conn.sync();// 清空Jedis設置的keycommands.flushdb();//keysList<String> list = commands.keys("*");for (String s : list) {System.out.println(s);}//Stringcommands.set("k1", "hello Lettuce");String s1 = commands.get("k1");System.out.println("String s ===" + s1);//listcommands.lpush("myList2", "v1", "v2", "v3");List<String> list2 = commands.lrange("myList2", 0, -1);for (String s : list2) {System.out.println("list ssss===" + s);}//setcommands.sadd("mySet2", "v1", "v2", "v3");Set<String> set = commands.smembers("mySet2");for (String s : set) {System.out.println("set ssss===" + s);}//hashMap<String, String> map = new HashMap<>();map.put("k1", "138xxxxxxxx");map.put("k2", "fatigue");map.put("k3", "zzyybs@126.com");//課后有問題請給我發郵件commands.hmset("myHash2", map);Map<String, String> retMap = commands.hgetall("myHash2");for (String k : retMap.keySet()) {System.out.println("hash  k=" + k + " , v==" + retMap.get(k));}//zSetcommands.zadd("myzSet2", 100.0, "s1", 110.0, "s2", 90.0, "s3");List<String> list3 = commands.zrange("myzSet2", 0, 10);for (String s : list3) {System.out.println("zSet ssss===" + s);}//sortSortArgs sortArgs = new SortArgs();sortArgs.alpha();sortArgs.desc();List<String> list4 = commands.sort("myList2", sortArgs);for (String s : list4) {System.out.println("sort ssss===" + s);}//關閉conn.close();client.shutdown();}
}

2.2、連接Redis集群
public class LettuceColonyDemoTest {public static void main(String[] args) {HashSet<RedisURI> uris = new HashSet<>();uris.add(RedisURI.builder().withHost("192.168.112.129").withPort(6379).withAuthentication("default", "root").build());uris.add(RedisURI.builder().withHost("192.168.112.130").withPort(6381).withAuthentication("default", "root").build());uris.add(RedisURI.builder().withHost("192.168.112.129").withPort(6380).withAuthentication("default", "root").build());RedisClusterClient client = RedisClusterClient.create(uris);StatefulRedisClusterConnection<String, String> con = client.connect();RedisAdvancedClusterCommands<String, String> clusterCommands = con.sync();// 清除單機Redis設置的key// Lettuce連接Redis集群模式下,能使用flushAll命令// 因為Lettuce內部實現了智能的路由機制,能夠自動將 KEYS 命令分發到集群中的各個節點,并將結果聚合返回clusterCommands.flushallAsync();//keysList<String> list = clusterCommands.keys("*");for (String s : list) {System.out.println(s);}//StringclusterCommands.set("k1", "hello Lettuce");String s1 = clusterCommands.get("k1");System.out.println("redis集群===" + s1);//listclusterCommands.lpush("myList2", "v1", "v2", "v3");List<String> list2 = clusterCommands.lrange("myList2", 0, -1);for (String s : list2) {System.out.println("list ssss===" + s);}//setclusterCommands.sadd("mySet2", "v1", "v2", "v3");Set<String> set = clusterCommands.smembers("mySet2");for (String s : set) {System.out.println("set ssss===" + s);}//hashMap<String, String> map = new HashMap<>();map.put("k1", "138xxxxxxxx");map.put("k2", "fatigue");map.put("k3", "zzyybs@126.com");//課后有問題請給我發郵件clusterCommands.hmset("myHash2", map);Map<String, String> retMap = clusterCommands.hgetall("myHash2");for (String k : retMap.keySet()) {System.out.println("hash  k=" + k + " , v==" + retMap.get(k));}//zSetclusterCommands.zadd("myzSet2", 100.0, "s1", 110.0, "s2", 90.0, "s3");List<String> list3 = clusterCommands.zrange("myzSet2", 0, 10);for (String s : list3) {System.out.println("zSet ssss===" + s);}//sortSortArgs sortArgs = new SortArgs();sortArgs.alpha();sortArgs.desc();List<String> list4 = clusterCommands.sort("myList2", sortArgs);for (String s : list4) {System.out.println("sort ssss===" + s);}//關閉con.close();client.shutdown();client.close();}
}

3、測試用例

3.1、單機測試結果

?控制臺輸出:

redis客戶端:


3.2、redis集群測試結果

控制臺輸出:

redis客戶端:


(三)、集成RedisTemplate

1、新建配置文件

新建application.properties文件:

server.port=8080
spring.application.name=RedisDemo
# ========================logging=====================
logging.level.root=info
logging.level.xxx.xx.xxx=info
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%nlogging.file.name=D:/myLogs/RedisDemo.log
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n# ========================redis單機=====================
spring.data.redis.database=0
#修改為自己的真實IP
spring.data.redis.host=xxx.xxx.xxx.xxx
spring.data.redis.port=6379
spring.data.redis.password=xxxx
spring.data.redis.lettuce.pool.max-active=8
spring.data.redis.lettuce.pool.max-wait=-1ms
spring.data.redis.lettuce.pool.max-idle=8
spring.data.redis.lettuce.pool.min-idle=0

2、導入依賴

        <!--SpringBoot通用依賴模塊--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--SpringBoot與Redis整合依賴--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!--日志--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.24.3</version></dependency><!-- swagger3生成接口文檔依賴--><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.3.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency>

3、編寫業務類

3.1、新建controller
@RestController
@Tag(name = "訂單管理", description = "訂單的創建和查詢操作")
public class OrderController {@Resourceprivate OrderService orderService;/*** redis單機*/@RequestMapping(value = "/order/add", method = RequestMethod.POST)public void addOrder() {orderService.addOrder();}@RequestMapping(value = "/order/{id}", method = RequestMethod.GET)public String findUserById(@PathVariable Integer id) {return orderService.getOrderById(id);}/*** redis集群*/@RequestMapping(value = "/cluster/order/add", method = RequestMethod.POST)public void clusterAddOrder() {orderService.clusterAddOrder();}@RequestMapping(value = "cluster/order/{id}", method = RequestMethod.GET)public String clusterFindUserById(@PathVariable Integer id) {return orderService.clusterFindUserById(id);}
}

3.2、新建service

*注意:只編寫String類型的數據操作,其他類型的API操作,私底下練習

@Service
@Slf4j
public class OrderService {public static final String ORDER_KEY = "order:";@Resourceprivate RedisTemplate<String, String> redisTemplate;public void addOrder() {int keyId = ThreadLocalRandom.current().nextInt(1000) + 1;String orderNo = UUID.randomUUID().toString();redisTemplate.opsForValue().set(ORDER_KEY + keyId, "訂單編號" + orderNo);log.info("redis單機=====>編號{}的訂單流水生成:{}", keyId, orderNo);}public String getOrderById(Integer id) {System.out.println(redisTemplate.opsForList().range("myList", 0, -1));HashMap<String, String> map = new HashMap<>();map.put("k1", "k2");map.put("k3", "k4");map.put("k5", "k6");redisTemplate.opsForValue().multiSet(map);return redisTemplate.opsForValue().get(ORDER_KEY + id);}public void clusterAddOrder() {int keyId = ThreadLocalRandom.current().nextInt(1000) + 1;String orderNo = UUID.randomUUID().toString();redisTemplate.opsForValue().set(ORDER_KEY + keyId, "訂單編號" + orderNo);log.info("redis集群=====>編號{}的訂單流水生成:{}", keyId, orderNo);}public String clusterFindUserById(Integer id) {return redisTemplate.opsForValue().get(ORDER_KEY + id);}
}

3.3、新建config

這個配置主要是生成接口文檔。

@Configuration
public class OpenAPIConfig {@Beanpublic OpenAPI customOpenAPI() {String currentDate = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDateTime.now());return new OpenAPI().info(new Info().title("springBoot利用swagger3構建api接口文檔 " + "\t" + currentDate).description("springboot+redis整合").version("1.0").termsOfService("https://www.baidu.com/"));}
}

3.4、連接redis單機


3.5、連接redis集群


4、測試接口

啟動項目,訪問http://localhost:8080/swagger-ui/index.html

4.1、單機測試結果

控制臺輸出:

redis客戶端:

Q:數據是存進去了,但是為啥是亂碼的?在連接redis客戶端的時候加上了--raw的參數還是亂碼?為啥通過接口獲取的數據是正常的,但是通過redis客戶端去查看的又是亂碼?

A:是因為序列化方式不一致造成。鍵(key)和值(value)都是通過spring提供的Serializer序列化到數據庫的。RedisTemplate默認使用的是JdkSerializationRedisSerializer。解決辦法就是統一序列化方式。

新建RedisConfig類:

@Configuration
public class RedisConfig {/***設置存儲key的序列化方式* @param redisConnectionFactory 創建與Redis連接的工廠類*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);//設置StringredisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setValueSerializer(new StringRedisSerializer());// 設置hash、set、zSet、list.....redisTemplate.afterPropertiesSet();return redisTemplate;}
}

重啟項目,重新測試:

問題解決。


4.2、redis集群測試結果

修改application.properties文件,注釋redis單機配置:

重啟項目,進行測試:

redis客戶端:

初步看來,連接redis集群沒毛病。


Q:假設集群中,有主機服務宕機了,從機上位后,程序是否還能正常從redis集群獲取與寫入數據呢?

A:讀能正常但是寫不正常

手動關閉6379,模擬測試一下。

是需要手動開啟刷新節點拓撲網落的,

#支持集群拓撲動態感應刷新,自適應拓撲刷新是否使用所有可用的更新,默認false關閉
spring.data.redis.lettuce.cluster.refresh.adaptive=true
#定時刷新 毫秒
spring.data.redis.lettuce.cluster.refresh.period=2000

不然,當某個Master主機宕機后,雖然從機上位了,但還是不可用的(針對于這個key剛好落在宕機的Master上)。


(四)、集成Redisson

1、導入依賴

        <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.45.0</version></dependency>

2、編寫業務類

2.1、新建controller
@RestController
@Tag(name = "Redisson訂單管理", description = "訂單的創建和查詢操作")
public class RedissonOrderController {@Resourceprivate RedissonOrderService redissonOrderService;/*** redisson連接redis單機*/@RequestMapping(value = "/redisson/order/add", method = RequestMethod.POST)public void redissonAddOrder() {redissonOrderService.redissonAddOrder();}@RequestMapping(value = "/redisson/order/{id}", method = RequestMethod.GET)public String redissonFindUserById(@PathVariable Integer id) {return redissonOrderService.redissonFindUserById(id);}/*** redisson連接redis集群*/@RequestMapping(value = "/redisson/cluster/order/add", method = RequestMethod.POST)public void redissonClusterAddOrder() {redissonOrderService.redissonClusterAddOrder();}@RequestMapping(value = "/redisson/cluster/order/{id}", method = RequestMethod.GET)public String redissonClusterFindUserById(@PathVariable Integer id) {return redissonOrderService.redissonClusterFindUserById(id);}}

2.2、新建service

*注意:只編寫String類型的數據操作,其他類型的API操作,私底下練習。

@Service
@Slf4j
public class RedissonOrderService {public static final String ORDER_KEY = "order:";private final RedissonClient redissonSingleClient;private final RedissonClient redissonColonyClient;@Autowiredpublic RedissonOrderService(@Qualifier("redissonColonyClient") RedissonClient redissonColonyClient,@Qualifier("redissonSingleClient") RedissonClient redissonSingleClient) {this.redissonColonyClient = redissonColonyClient;this.redissonSingleClient = redissonSingleClient;}public void redissonAddOrder() {int keyId = ThreadLocalRandom.current().nextInt(1000) + 1;String orderNo = UUID.randomUUID().toString();redissonSingleClient.getBucket(ORDER_KEY + keyId).set("訂單編號" + orderNo);log.info("redisson連接redis單機=====>編號{}的訂單流水生成:{}", keyId, orderNo);}public String redissonFindUserById(Integer id) {RBucket<Object> bucket = redissonSingleClient.getBucket(ORDER_KEY + id);return (String) bucket.get();}public void redissonClusterAddOrder() {int keyId = ThreadLocalRandom.current().nextInt(1000) + 1;String orderNo = UUID.randomUUID().toString();redissonColonyClient.getBucket(ORDER_KEY + keyId).set("訂單編號" + orderNo);log.info("redisson連接redis集群=====>編號{}的訂單流水生成:{}", keyId, orderNo);}public String redissonClusterFindUserById(Integer id) {RBucket<Object> bucket = redissonColonyClient.getBucket(ORDER_KEY + id);return (String) bucket.get();}
}

2.3、新建config
@Configuration
public class RedissonConfig {/*** redisson連接redis單機*/@Bean(name = "redissonSingleClient")@Primarypublic RedissonClient redissonSingleClient() {Config config = new Config();// 單機模式config.useSingleServer().setAddress("redis://192.168.112.131:6381").setPassword("root");// 設置 JSON 序列化編解碼器config.setCodec(new JsonJacksonCodec(new ObjectMapper()));return Redisson.create(config);}/*** redisson連接redis集群*/@Bean(name = "redissonColonyClient")public RedissonClient redissonColonyClient() {Config config = new Config();// 設置JSON序列化編解碼器config.setCodec(new JsonJacksonCodec(new ObjectMapper()));// 集群模式config.useClusterServers().addNodeAddress("redis://192.168.112.129:6379","redis://192.168.112.129:6380","redis://192.168.112.130:6381","redis://192.168.112.130:6382","redis://192.168.112.131:6383","redis://192.168.112.131:6384").setScanInterval(2000)// 集群狀態掃描間隔時間,單位是毫秒.setPassword("root");return Redisson.create(config);}
}

2.4、連接redis單機


2.5、連接redis集群


3、測試接口

3.1、單機測試結果

控制臺輸出:

redis客戶端:


3.2、redis集群測試結果

控制臺輸出:

redis客戶端:


三、總結

在Java開發中,與 Redis 進行高效整合是提升系統性能和可擴展性的關鍵環節。本文為你詳細介紹四種主流的Java整合Redis的方式,涵蓋底層客戶端庫Jedis和Lettuce,以及上層框架封裝RedisTemplate和Redisson。

Jedis以其簡單易懂的使用方式脫穎而出,對于剛剛接觸 Redis 集成的初學者而言,它就像一位耐心的導師,引導著開發者逐步熟悉 Redis的操作。同時,由于其在單線程環境下表現穩定,成為單線程應用場景的理想選擇。

Lettuce則憑借卓越的性能在高并發領域獨樹一幟。它基于 Netty 實現,具備出色的異步處理能力和線程安全性,能夠在高并發的浪潮中穩健前行,為高并發場景提供強大的支持。

RedisTemplate與Spring框架深度融合,仿佛是為Spring項目量身定制的利器。在 Spring 項目中,使用RedisTemplate可以輕松地與其他Spring組件協同工作,極大地提高了開發效率,讓開發者能夠更加專注于業務邏輯的實現。

Redisson作為一個獨立的框架,不依賴于任何特定的框架,它專注于分布式系統的開發,提供了豐富的分布式數據結構和服務,如分布式鎖、分布式集合等,為分布式系統的搭建提供了全方位的解決方案。

在實際的項目開發中,我們應根據項目的具體需求和應用場景,審慎地選擇合適的整合方式。希望本文能夠幫助你更好地掌握 Java與Redis的集成技術,為項目注入強大的性能和可擴展性動力。


ps:努力到底,讓持續學習成為貫穿一生的堅守。學習筆記持續更新中。。。。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/71067.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/71067.shtml
英文地址,請注明出處:http://en.pswp.cn/web/71067.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《國密算法開發實戰:從合規落地到性能優化》

前言 隨著信息技術的飛速發展,信息安全已成為全球關注的焦點。在數字化時代,數據的保密性、完整性和可用性直接關系到國家、企業和個人的利益。為了保障信息安全,密碼技術作為核心支撐,發揮著至關重要的作用。國密算法,即國家密碼算法,是我國自主設計和推廣的一系列密碼…

yolov12 部署瑞芯微 rk3588、RKNN 部署工程難度小、模型推理速度快

yolov12 部署又來了。 特別說明&#xff1a;如有侵權告知刪除&#xff0c;謝謝。 完整代碼&#xff1a;包括onnx轉rknn和測試代碼、rknn板端部署C代碼&#xff1a; 【onnx轉rknn和測試代碼】 【rknn板端部署C代碼】 1 模型訓練 yolov12訓練官方開源的已經非常詳細了&#…

windows本地化部署Dify+Deepseek

Windows本地化部署DifyDeepseek 一、下載Docker 前往 Docker 官網 下載 Docker Desktop&#xff0c;按序安裝。 1.1啟用WSL 打開本機的控制面板>程序>啟用或關閉 Windows 功能,勾選: Linux 的 Windows 子系統虛擬機平臺&#xff08;若無該選擇則勾選 Hyper-V &#…

使用Spring Boot與達夢數據庫(DM)進行多數據源配置及MyBatis Plus集成

使用Spring Boot與達夢數據庫(DM)進行多數據源配置及MyBatis Plus集成 在現代企業級應用開發中&#xff0c;處理多個數據源是一個常見的需求。本文將詳細介紹如何使用Spring Boot結合達夢數據庫&#xff08;DM&#xff09;&#xff0c;并通過MyBatis Plus來簡化數據庫操作&…

第二十四:5.2【搭建 pinia 環境】axios 異步調用數據

第一步安裝&#xff1a;npm install pinia 第二步&#xff1a;操作src/main.ts 改變里面的值的信息&#xff1a; <div class"count"><h2>當前求和為&#xff1a;{{ sum }}</h2><select v-model.number"n">  // .number 這里是…

使用 DeepSeek 生成流程圖、甘特圖與思維導圖:結合 Typora 和 XMind 的高效工作流

在現代工作與學習中&#xff0c;可視化工具如流程圖、甘特圖和思維導圖能夠極大地提升信息整理與表達的效率。本文將詳細介紹如何使用 DeepSeek 生成 Mermaid 文本&#xff0c;結合 Typora 快速生成流程圖和甘特圖&#xff0c;并通過 Markdown 格式生成思維導圖&#xff0c;最終…

DeepSeek 開源周:第五天 - Fire-Flyer 文件系統(3FS)

&#xff08;下面文字主要由 Grok 3 協助生成&#xff09; 概述 Deepseek 今天開源的 Fire-Flyer 文件系統&#xff08;3FS&#xff09;是一個高性能分布式文件系統&#xff0c;專門為 AI 訓練和推理設計。研究表明&#xff0c;它解決了 AI 工作負載中處理海量數據的高效存儲需…

【筆記】論文閱讀方法(AI大模型)

1 為什么讀論文 構建知識體系&#xff1a;通過Related Works快速了解該方向研究現狀&#xff0c;追蹤經典論文 緊跟前沿技術&#xff1a;了解領域內新技術及效果&#xff0c;快速借鑒到自身項目 培養科研邏輯&#xff1a;熟悉論文體系&#xff0c;了解如何創造新事物&#x…

【數據集】ACM數據集

ACM&#xff08;Association for Computing Machinery&#xff09;數據集是計算機科學領域常用于研究學術論文、作者關系、引文網絡、推薦系統、圖神經網絡&#xff08;GNN&#xff09;等任務的數據集之一。該數據集通常包含學術論文、作者、研究領域以及它們之間的關系&#x…

SQL server配置ODBC數據源(本地和服務器)

本地配置 1. 控制面板中找到系統ODBC數據源&#xff08;打開控制面板直接搜&#xff09; 2. 選擇“系統DSN”&#xff0c;點擊“添加” 3. 選擇“SQL server” 4. 名稱和描述自己填&#xff0c;服務器選擇本機設備名稱 5. 選擇ID和密碼驗證&#xff0c;并填寫本地SQL server登…

使用 Postman 訪問 Keycloak 端點

1. 引言 在本教程中&#xff0c;我們將首先快速回顧 OAuth 2.0、OpenID 和 Keycloak。然后&#xff0c;我們將了解 Keycloak REST API 以及如何在 Postman 中調用它們。 2. OAuth 2.0 OAuth 2.0 是一個授權框架&#xff0c;它允許經過身份驗證的用戶通過令牌向第三方授予訪問…

文生圖開源模型發展史(2014-2025年)

文生圖開源模型的發展歷程是一段充滿技術革新、社區生態繁榮與商業化競爭的多維度演進史。 一、技術萌芽期&#xff08;2014-2020年&#xff09; 核心突破 2014年&#xff1a;GAN&#xff08;生成對抗網絡&#xff09;誕生&#xff0c;首次實現數據驅動式圖像生成&#xff0…

微服務學習(2):實現SpringAMQP對RabbitMQ的消息收發

目錄 SpringAMQP是什么 為什么采用SpringAMQP SpringAMQP應用 準備springBoot工程 實現消息發送 SpringAMQP是什么 Spring AMQP是Spring框架下用于簡化AMQP&#xff08;高級消息隊列協議&#xff09;應用開發的一套工具集&#xff0c;主要針對RabbitMQ等消息中間件的集成…

AI人工智能機器學習之神經網絡

1、概要 本篇學習AI人工智能機器學習之神經網絡&#xff0c;以MLPClassifier和MLPRegressor為例&#xff0c;從代碼層面講述最常用的神經網絡模型MLP。 2、神經網絡 - 簡介 在 Scikit-learn 中&#xff0c;神經網絡是通過 sklearn.neural_network 模塊提供的。最常用的神經網…

WPF高級 | WPF 與數據庫交互:連接、查詢與數據更新

WPF高級 | WPF 與數據庫交互&#xff1a;連接、查詢與數據更新 前言一、數據庫交互基礎概念1.1 數據庫簡介1.2 數據訪問技術 二、WPF 與數據庫連接2.1 連接字符串2.2 建立連接 三、WPF 中的數據查詢3.1 使用ADO.NET進行數據查詢3.2 使用 Entity Framework 進行數據查詢3.3 使用…

【ESP32S3接入訊飛在線語音識別】

【ESP32S3接入訊飛在線語音識別】 1. 前言1.1 步驟概括1.2 硬件介紹1.3 接線2. 操作流程2.1 創建語音識別應用2.2 記錄API秘鑰3. JSON語音接入api3.1 JSON格式3.2 交互流程3.2 ESP32S3 Sense接入代碼1. 核心功能2. 主要模塊3. 工作流程4. 典型應用場景5. 關鍵技術點6. 待完善功…

學生管理前端

文章目錄 首頁student.html查詢功能 首頁 SpringBoot前端html頁面放在static文件夾下&#xff1a;/src/main/resources/static 默認首頁為index.html&#xff0c;我們可以用兩個超鏈接或者兩個button跳轉到對應的頁面。這里只是單純的跳轉頁面&#xff0c;不需要提交表單等其…

(動態規劃 最長遞增的子序列)leetcode 300

這道題我第一眼反應就是暴力&#xff0c;但是暴力的話就是n*n-1*n-2*...n-(n-1) 也就是O(n^n)dfs做絕對超時 貪心也不行&#xff0c;這里是子序列&#xff0c;要考慮在ni的范圍內考慮多種路線取最優&#xff0c;所以用動態規劃 如何用動態規劃呢&#xff1f; 答&#xff1a;…

RabbitMQ系列(六)基本概念之Routing Key

在 RabbitMQ 中&#xff0c;Routing Key&#xff08;路由鍵&#xff09; 是用于將消息從交換機&#xff08;Exchange&#xff09;路由到指定隊列&#xff08;Queue&#xff09;的關鍵參數。其核心作用是通過特定規則匹配綁定關系&#xff0c;確保消息被正確分發。以下是其核心機…

Spark內存并行計算框架

spark核心概念 spark集群架構 spark集群安裝部署 spark-shell的使用 通過IDEA開發spark程序 1. Spark是什么 Apache Spark? is a unified analytics engine for large-scale data processingspark是針對于大規模數據處理的統一分析引擎 spark是在Hadoop基礎上的改進&…