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.mzph.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基础上的改进&…