歡迎光臨
每天分享高質量文章

一起來學 SpringBoot 2.x | 第九篇:整合 Lettuce Redis

點選上方“芋道原始碼”,選擇“置頂公眾號”

技術文章第一時間送達!

原始碼精品專欄

 


摘要: 原創出處 http://blog.battcn.com/2018/05/11/springboot/v2-nosql-redis/ 「唐亞峰」歡迎轉載,保留摘要,謝謝!

  • Redis介紹

  • Lettuce

  • 匯入依賴

  • 屬性配置

  • 具體編碼

  • 總結

  • 說點什麼


SpringBoot 是為了簡化 Spring 應用的建立、執行、除錯、部署等一系列問題而誕生的產物,自動裝配的特性讓我們可以更好的關註業務本身而不是外部的XML配置,我們只需遵循規範,引入相關的依賴就可以輕易的搭建出一個 WEB 工程

Spring Boot 除了支援常見的ORM框架外,更是對常用的中介軟體提供了非常好封裝,隨著Spring Boot2.x的到來,支援的元件越來越豐富,也越來越成熟,其中對Redis的支援不僅僅是豐富了它的API,更是替換掉底層Jedis的依賴,取而代之換成了Lettuce(生菜)

Redis介紹

Redis是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。相比Memcached它支援儲存的型別相對更多(字元、雜湊、集合、有序集合、串列、GEO)同時Redis是執行緒安全的。2010年3月15日起,Redis的開發工作由VMware主持,2013年5月開始,Redis的開發由Pivotal贊助。

Lettuce

Lettuce  Jedis 的都是連線Redis Server的客戶端程式。Jedis實現上是直連redis server,多執行緒環境下非執行緒安全,除非使用連線池,為每個Jedis實體增加物理連線Lettuce基於Netty的連線實體(StatefulRedisConnection),可以在多個執行緒間併發訪問,且執行緒安全,滿足多執行緒環境下的併發訪問,同時它是可伸縮的設計,一個連線實體不夠的情況也可以按需增加連線實體

匯入依賴

 pom.xml spring-boot-starter-data-redis的依賴,Spring Boot2.x 後底層不在是Jedis如果做版本升級的朋友需要註意下

<dependency>
    <groupId>org.springframework.bootgroupId>


    <artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
    <groupId>org.apache.commonsgroupId>
    <artifactId>commons-pool2artifactId>
dependency>
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-testartifactId>
    <scope>testscope>
dependency>

屬性配置

 application.properties 檔案中配置如下內容,由於Spring Boot2.x 的改動,連線池相關配置需要透過spring.redis.lettuce.pool或者 spring.redis.jedis.pool 進行配置了

spring.redis.host=localhost
spring.redis.password=battcn
# 連線超時時間(毫秒)
spring.redis.timeout=10000
# Redis預設情況下有16個分片,這裡配置具體使用的分片,預設是0
spring.redis.database=0
# 連線池最大連線數(使用負值表示沒有限制) 預設 8
spring.redis.lettuce.pool.max-active=8
# 連線池最大阻塞等待時間(使用負值表示沒有限制) 預設 -1
spring.redis.lettuce.pool.max-wait=-1
# 連線池中的最大空閑連線 預設 8
spring.redis.lettuce.pool.max-idle=8
# 連線池中的最小空閑連線 預設 0
spring.redis.lettuce.pool.min-idle=0

具體編碼

Spring BootRedis的支援已經非常完善了,良好的序列化以及豐富的API足夠應對日常開發

物體類

建立一個User

package com.battcn.entity;

import java.io.Serializable;

/**
 * @author Levin
 * @since 2018/5/10 0007
 */

public class User implements Serializable {

    private static final long serialVersionUID = 8655851615465363473L;
    private Long id;
    private String username;
    private String password;
    // TODO  省略get set
}

自定義Template

預設情況下的模板只能支援RedisTemplate,也就是隻能存入字串,這在開發中是不友好的,所以自定義模板是很有必要的,當自定義了模板又想使用String儲存這時候就可以使用StringRedisTemplate的方式,它們並不衝突…

package com.battcn.config;

import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.io.Serializable;

/**
 * TODO 修改database
 *
 * @author Levin
 * @since 2018/5/10 0022
 */

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheAutoConfiguration {

    @Bean
    public RedisTemplate redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
        RedisTemplate template = new RedisTemplate<>();
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

測試

完成準備事項後,編寫一個junit測試類來檢驗程式碼的正確性,有很多人質疑過Redis執行緒安全性,故下麵也提供了響應的測試案例,如有疑問歡迎指正

package com.battcn;

import com.battcn.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;

import java.io.Serializable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;

/**
 * @author Levin
 * @since 2018/5/10 0010
 */

@RunWith(SpringRunner.class)
@SpringBootTest
public class Chapter8ApplicationTest {

    private static final Logger log = LoggerFactory.getLogger(Chapter8ApplicationTest.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisTemplate redisCacheTemplate;


    @Test
    public void get() {
        // TODO 測試執行緒安全
        ExecutorService executorService = Executors.newFixedThreadPool(1000);
        IntStream.range(01000).forEach(i ->
                executorService.execute(() -> stringRedisTemplate.opsForValue().increment("kk"1))
        );
        stringRedisTemplate.opsForValue().set("k1""v1");
        final String k1 = stringRedisTemplate.opsForValue().get("k1");
        log.info("[字元快取結果] - [{}]", k1);
        // TODO 以下只演示整合,具體Redis命令可以參考官方檔案,Spring Data Redis 只是改了個名字而已,Redis支援的命令它都支援
        String key = "battcn:user:1";
        redisCacheTemplate.opsForValue().set(key, new User(1L"u1""pa"));
        // TODO 對應 String(字串)
        final User user = (User) redisCacheTemplate.opsForValue().get(key);
        log.info("[物件快取結果] - [{}]", user);
    }
}

其它型別

下列的就是Redis其它型別所對應的操作方式

  • opsForValue: 對應 String(字串)

  • opsForZSet: 對應 ZSet(有序集合)

  • opsForHash: 對應 Hash(雜湊)

  • opsForList: 對應 List(串列)

  • opsForSet: 對應 Set(集合)

  • opsForGeo: 對應 GEO(地理位置)

總結

spring-data-redis檔案: https://docs.spring.io/spring-data/redis/docs/2.0.1.RELEASE/reference/html/#new-in-2.0.0
Redis 檔案: https://redis.io/documentation
Redis 中文檔案: http://www.redis.cn/commands.html

目前很多大佬都寫過關於 SpringBoot 的教程了,如有雷同,請多多包涵,本教程基於最新的 spring-boot-starter-parent:2.0.1.RELEASE編寫,包括新版本的特性都會一起介紹…

說點什麼

全文程式碼:https://github.com/battcn/spring-boot2-learning/tree/master/chapter8




如果你對 Dubbo / Netty 等等原始碼與原理感興趣,歡迎加入我的知識星球一起交流。長按下方二維碼噢

目前在知識星球更新了《Dubbo 原始碼解析》目錄如下:

01. 除錯環境搭建
02. 專案結構一覽
03. 配置 Configuration
04. 核心流程一覽

05. 拓展機制 SPI

06. 執行緒池

07. 服務暴露 Export

08. 服務取用 Refer

09. 註冊中心 Registry

10. 動態編譯 Compile

11. 動態代理 Proxy

12. 服務呼叫 Invoke

13. 呼叫特性 

14. 過濾器 Filter

15. NIO 伺服器

16. P2P 伺服器

17. HTTP 伺服器

18. 序列化 Serialization

19. 叢集容錯 Cluster

20. 優雅停機

21. 日誌適配

22. 狀態檢查

23. 監控中心 Monitor

24. 管理中心 Admin

25. 運維命令 QOS

26. 鏈路追蹤 Tracing

… 一共 69+ 篇

目前在知識星球更新了《Netty 原始碼解析》目錄如下:

01. 除錯環境搭建
02. NIO 基礎
03. Netty 簡介
04. 啟動 Bootstrap

05. 事件輪詢 EventLoop

06. 通道管道 ChannelPipeline

07. 通道 Channel

08. 位元組緩衝區 ByteBuf

09. 通道處理器 ChannelHandler

10. 編解碼 Codec

11. 工具類 Util

… 一共 61+ 篇

目前在知識星球更新了《資料庫物體設計》目錄如下:


01. 商品模組
02. 交易模組
03. 營銷模組
04. 公用模組

… 一共 17+ 篇

贊(0)

分享創造快樂