本文代码对应的github地址:https://github.com/nieandsun/redis-study
不出意外的话,很多公司操作redis应该还是使用的jedis。
当然应该也有公司比较
能耐
,直接把操作redis的所有方法进一步封装成API或Utils类,然后打成jar包,做成服务供多个部门使用 —》 然后开发者就不必关心真正与redis交互的细节了。— 其实我们公司就是这种姿势!!!
不知道其他公司到底是怎么个套路,我觉得这种方式对公司挺好,但是对于我们开发者自身来说,可能就缺少了直面问题 + 解决问题的机会。
其实说实话,我们组也在做一些基础性的服务,从这个角度来讲,貌似每个部门(或许更应该说是每一个coder吧)都希望自己可以直面问题,直面挑战,然后让别人使用自己提供的服务!!!
不知道是不是每个人都是这么想的,但至少我感觉貌似我身边的好些人都表现出了这种姿态!!!
1 jedis和lettuce简单比较
-
Jedis
在实现上是直接连接Redis服务器,在多个线程间共享一个Jedis 实例时是线程不安全的
,如果想要在多线程场景下使用Jedis,需要使用连接池,每个线程都使用自己的Jedis实例,当连接数量增多时,会消耗较多的物理资源。 -
与Jedis相比,
lettuce
则完全克服了其线程不安全的缺点:lettuce 是一个可伸缩的线程安全的 Redis客户端,支持同步、异步和响应式模式。多个线程可以共享一个连接实例, 而不必担心多线程并发问题。它基于优秀Netty NIO框架构建,支持Redis的更多高级功能。
2 springboot集成redis
2.1 添加依赖
maven依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- lettuce连接池需要依赖下面的jar包 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2.2 数据源配置
spring:
redis:
database: 0 #使用第几个数据库
host: 192.168.65.135 #redis服务器地址
port: 6379 #端口号
password: 123456 #redis服务器连接密码
timeout: 10000ms # 连接超时时间(毫秒)
lettuce:
pool:
##下面的值其实是lettuce连接池的默认配置,有兴趣的可以点进源码看一下
max-active: 8 #连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms #连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 8 #连接池中的最大空闲连接
min-idle: 0 #连接池中的最小空闲连接
2.3 配置类
实际上完成2.2就可以了,但是由于springboot默认提供的redis操作模版类 —RedisTemplate实际上为<Object,Object>类型,但是相信大家都知道,我们平常使用redis,key都会使用一个相对简单的字符串,因此我们需要自己配置一个RedisTemplate,具体原理可以看一下下面的文章,这里我不过多叙述 —》但是那篇文章数据源那一块是有问题的
https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html#!comments
扫描二维码关注公众号,回复: 11282945 查看本文章
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
3 简单测试
测试程序如下:
package com.nrsc.redis.learning.simple;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class RedisSimpleDemo {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void test1() {
redisTemplate.multi();
redisTemplate.opsForValue().set("k1", "Hello Redis1....");
int i = 100 / 0;
redisTemplate.opsForValue().set("k2", "Hello Redis2....");
redisTemplate.exec();
}
@Test
public void test2() {
stringRedisTemplate.multi();
stringRedisTemplate.opsForValue().set("k1", "Hello Redis1....");
int i = 100 / 0;
stringRedisTemplate.opsForValue().set("k2", "Hello Redis2....");
stringRedisTemplate.exec();
}
}
可以得到的结论:
(1)test1方法运行之后,数据库里什么值都插入不进去,但test2运行后可以插入k1对应的值 —》 说明:
- 我们配置的事务生效了。
- 当然如果想让StringRedisTemplate可以开启事务,我们可以按照RedisTemplate一样配置一个我们自己的StringRedisTemplate
(2)无论是RedisTemplate还是StringRedisTemplate,都使用了我们配置的连接池信息,有兴趣的可以通过打断点的方式看一下RedisTemplate或StringRedisTemplate实例中的connectionFactory,举例如下:
end !