原文部落格地址: pjmike的部落格
前言
在實際專案開發過程中,相信很多人都有用到過 redis 這個NoSQL,這篇文章就詳細講講springboot如何整合 redis
Redis 簡介
簡單介紹下Redis:
Redis是一個開源的使用 ANSI C語言編寫,支援網路,可基於記憶體也可持久化的日誌型,Key-Value資料庫,並提供了多種語言的 API ,相比
Memcached
它支援儲存的型別相對更多 (字元,雜湊,集合,有序集合,列表等),同時Redis是執行緒安全的。
Redis 連線池簡介
在後面 springboot 整合 redis 的時候會用到連線池,所以這裡先來介紹下 Redis中的連線池:
客戶端連線 Redis 使用的是 TCP協議,直連的方式每次需要建立 TCP連線,而連線池的方式是可以預先初始化好客戶端連線,所以每次只需要從 連線池借用即可,而借用和歸還操作是在本地進行的,只有少量的併發同步開銷,遠遠小於新建TCP連線的開銷。另外,直連的方式無法限制 redis客戶端物件的個數,在極端情況下可能會造成連線洩漏,而連線池的形式可以有效的保護和控制資源的使用。
下面以Jedis客戶端為例,再來總結下 客戶端直連方式和連線池方式的對比
優點 | 缺點 | |
---|---|---|
直連 | 簡單方便,適用於少量長期連線的場景 | 1. 存在每次新建/關閉TCP連線開銷 2. 資源無法控制,極端情況下出現連線洩漏 3. Jedis物件執行緒不安全(Lettuce物件是執行緒安全的) |
連線池 | 1. 無需每次連線生成Jedis物件,降低開銷 2. 使用連線池的形式保護和控制資源的使用 | 相對於直連,使用更加麻煩,尤其在資源的管理上需要很多引數來保證,一旦規劃不合理也會出現問題 |
Jedis vs Lettuce
redis官方提供的java client有如圖所示幾種:
![redis](https://i.iter01.com/images/0450f7d8b61a74d1dbe6ee0d52b0a7d73af0b0ef06fb4f21e0b6376afacc5fda.png)
Lettuce 是 一種可伸縮,執行緒安全,完全非阻塞的Redis客戶端,多個執行緒可以共享一個RedisConnection,它利用Netty NIO 框架來高效地管理多個連線,從而提供了非同步和同步資料訪問方式,用於構建非阻塞的反應性應用程式。
在 springboot 1.5.x版本的預設的Redis客戶端是 Jedis
實現的,springboot 2.x版本中預設客戶端是用 lettuce
實現的。
下面介紹 springboot 2.0
分別使用 jedis
和 lettuce
整合 redis服務
springboot 2.0 通過 lettuce整合Redis服務
匯入依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
複製程式碼
application.properties配置檔案
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=root
# 連線池最大連線數(使用負值表示沒有限制) 預設為8
spring.redis.lettuce.pool.max-active=8
# 連線池最大阻塞等待時間(使用負值表示沒有限制) 預設為-1
spring.redis.lettuce.pool.max-wait=-1ms
# 連線池中的最大空閒連線 預設為8
spring.redis.lettuce.pool.max-idle=8
# 連線池中的最小空閒連線 預設為 0
spring.redis.lettuce.pool.min-idle=0
複製程式碼
自定義 RedisTemplate
預設情況下的模板只能支援 RedisTemplate<String,String>
,只能存入字串,很多時候,我們需要自定義 RedisTemplate ,設定序列化器,這樣我們可以很方便的操作例項物件。如下所示:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory connectionFactory) {
RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
複製程式碼
定義測試實體類
public class User implements Serializable {
private static final long serialVersionUID = 4220515347228129741L;
private Integer id;
private String username;
private Integer age;
public User(Integer id, String username, Integer age) {
this.id = id;
this.username = username;
this.age = age;
}
public User() {
}
//getter/setter 省略
}
複製程式碼
測試
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
private Logger logger = LoggerFactory.getLogger(RedisTest.class);
@Autowired
private RedisTemplate<String, Serializable> redisTemplate;
@Test
public void test() {
String key = "user:1";
redisTemplate.opsForValue().set(key, new User(1,"pjmike",20));
User user = (User) redisTemplate.opsForValue().get(key);
logger.info("uesr: "+user.toString());
}
}
複製程式碼
springboot 2.0 通過 jedis 整合Redis服務
匯入依賴
因為 springboot2.0中預設是使用 Lettuce來整合Redis服務,spring-boot-starter-data-redis
預設只引入了 Lettuce
包,並沒有引入 jedis
包支援。所以在我們需要手動引入 jedis
的包,並排除掉 lettuce
的包,pom.xml配置如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
複製程式碼
application.properties配置
使用jedis的連線池
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=root
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.max-wait=-1ms
spring.redis.jedis.pool.min-idle=0
spring.redis.jedis.pool.max-active=8
複製程式碼
配置 JedisConnectionFactory
因為在 springoot 2.x版本中,預設採用的是 Lettuce實現的,所以無法初始化出 Jedis的連線物件 JedisConnectionFactory
,所以我們需要手動配置並注入:
public class RedisConfig {
@Bean
JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
return factory;
}
複製程式碼
但是啟動專案後發現報出瞭如下的異常:
![jedis_error](https://i.iter01.com/images/c19d4eb74815144f4a5df3b920127a6bf24ea1c171b86697797b11e2c942444a.png)
redis連線失敗,springboot2.x通過以上方式整合Redis並不會讀取配置檔案中的 spring.redis.host
等這樣的配置,需要手動配置,如下:
@Configuration
public class RedisConfig2 {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Bean
public RedisTemplate<String, Serializable> redisTemplate(JedisConnectionFactory connectionFactory) {
RedisTemplate<String, Serializable> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(jedisConnectionFactory());
return redisTemplate;
}
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPort(port);
config.setPassword(RedisPassword.of(password));
JedisConnectionFactory connectionFactory = new JedisConnectionFactory(config);
return connectionFactory;
}
}
複製程式碼
通過以上方式就可以連線上 redis了,不過這裡要提醒的一點就是,在springboot 2.x版本中 JedisConnectionFactory
設定連線的方法已過時,如圖所示:
![jedis_timeout](https://i.iter01.com/images/d0d4bd195ee02fa4c3e8c64db75be506a949d50cc8d3c8b2a6e698bc6edd67fe.png)
在 springboot 2.x
版本中推薦使用 RedisStandaloneConfiguration
類來設定連線的埠,地址等屬性
然後是單元測試,與上面 Lettuce
的例子程式碼一樣,並且測試通過。
小結
上面介紹springboot 2.x版本如何通過 Jedis 和 Lettuce 來整合Redis服務,原始碼地址如下:github.com/pjmike/spri…