<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot整合Redis做緩存,實(shí)戰(zhàn)分享

          共 7366字,需瀏覽 15分鐘

           ·

          2020-08-11 01:41

          每天早上七點(diǎn)三十,準(zhǔn)時推送干貨



          我們都知道,把首頁數(shù)據(jù)放到Redis里,能夠加快首頁數(shù)據(jù)的訪問速度。但是我們要如何準(zhǔn)確又快速的將 Redis 整合到自己的 SpringBoot2.x 項目中呢?今天阿粉就帶大家爬一爬其中的門門道道。

          Redis 介紹

          Redis 使用了浪費(fèi)流量的文本協(xié)議,但因為它數(shù)據(jù)存儲在內(nèi)存中的,相對而言,依然可以取得極高的訪問性能。并且 Redis 是線程安全的。

          RESP 就是 Redis 序列化協(xié)議的簡稱。它是一種直觀的文本協(xié)議,優(yōu)勢在于實(shí)現(xiàn)異常簡單,解析性能極好。

          Redis 協(xié)議里面雖然有大量冗余的回車換行符,但是這不影響它成為技術(shù)領(lǐng)域非常受歡迎的一個文本協(xié)議。在技術(shù)領(lǐng)域,性能并不總是一切,還有簡單性、易理解性和易實(shí)現(xiàn)性,這些都需要進(jìn)行適當(dāng)權(quán)衡。

          Redis 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)

          1、字符串:(緩存)

          • key:value

          value 可以是對象轉(zhuǎn)換成的 JSON 字符串,也可以是對象序列化后的二進(jìn)制字符串

          2、列表:(異步隊列) 類似linkedlist

          • 右邊進(jìn)左邊出:隊列
          • 右邊進(jìn)右邊出:棧

          3、字典(哈希) 類似hashmap:數(shù)組+鏈表

          不過rehash是漸進(jìn)式hash策略

          4、集合:(去重)

          • 無序 set:類似hashset
          • 有序 zset:類似SortedSet和HashMap的結(jié)合體,內(nèi)部實(shí)現(xiàn)是跳躍列表

          Lettuce

          隨著 Spring Boot2.x 的到來,支持的組件越來越豐富,也越來越成熟,其中對 Redis 的支持不僅僅是豐富了它的API,更是替換掉底層 Jedis 的依賴,取而代之換成了 Lettuce。

          雖然 Lettuce 和 Jedis 的都是連接 Redis Server 的客戶端程序,但是 Jedis 在實(shí)現(xiàn)上是直連 redis server,多線程環(huán)境下非線程安全,除非使用連接池,為每個Jedis實(shí)例增加物理連接。而 Lettuce 基于 Netty 的連接實(shí)例(StatefulRedisConnection),可以在多個線程間并發(fā)訪問,且線程安全,滿足多線程環(huán)境下的并發(fā)訪問,同時它是可伸縮的設(shè)計,一個連接實(shí)例不夠的情況也可以按需增加連接實(shí)例。

          Lettuce是可擴(kuò)展的Redis客戶端,用于構(gòu)建無阻塞的Reactive應(yīng)用程序.

          Luttuce官網(wǎng):https://lettuce.io/

          谷歌翻譯后的頁面是:

          原來這玩意兒叫生菜,你別說,看著圖標(biāo)還真有點(diǎn)像。


          實(shí)操

          項目中使用的 SpringBoot2.x 實(shí)現(xiàn),如果之前是 SpringBoot1.x 則需要注意,底層已經(jīng)由 Jedis 升級成了 Lettuce 。

          3.1、引入依賴

          除去 SpringBoot 項目需要的 jar 包外,另外還需要引入 redis 相關(guān)的依賴:


          ????org.springframework.boot
          ????spring-boot-starter-data-redis


          ????org.apache.commons
          ????commons-pool2

          3.2、application.yml 配置文件

          此處用到的 application.yml 文件,配置如下:

          spring:
          ??redis:
          ????# Redis默認(rèn)情況下有16個分片,這里配置具體使用的分片。默認(rèn)是索引為0的分片
          ????database:?1
          ????#?Redis服務(wù)器地址
          ????host:?127.0.0.1
          ????#?Redis服務(wù)器連接端口
          ????port:?6379
          ????#?Redis服務(wù)器連接密碼(默認(rèn)為空)
          ????password:?mmzsblog
          ????#?連接超時時間(毫秒)
          ????timeout:?2000s

          ????#?配置文件中添加?lettuce.pool?相關(guān)配置,則會使用到lettuce連接池
          ????lettuce:
          ??????pool:
          ????????#?連接池最大阻塞等待時間(使用負(fù)值表示沒有限制)?默認(rèn)?-1
          ????????max-wait:?60s
          ????????#?連接池中的最大空閑連接?默認(rèn)?8
          ????????max-idle:?10
          ????????#?連接池中的最小空閑連接?默認(rèn)?0
          ????????min-idle:?10
          ????????#?連接池最大連接數(shù)(使用負(fù)值表示沒有限制)?默認(rèn)?8
          ????????max-activ:?8

          如果項目是由 SpringBoot1.x 升級到 SpringBoot2.x 的,要沿用 jedis 連接池配置時會用到配置 jedis 相關(guān)的屬性:

          ????#?配置文件中添加?jedis.pool?相關(guān)配置,則會使用到?jedis?連接池
          ????jedis:
          ??????pool:
          ????????max-active:?10
          ????????max-idle:?8
          ????????min-idle:?0
          ????????max-wait:?60s

          并且引用的 jar 包也需要調(diào)整:

          <dependency>
          ????<groupId>org.springframework.bootgroupId>
          ????<artifactId>spring-boot-starter-data-redisartifactId>
          ????<exclusions>
          ????????<exclusion>
          ????????????<groupId>io.lettucegroupId>
          ????????????<artifactId>lettuce-coreartifactId>
          ????????exclusion>
          ????exclusions>
          dependency>
          <dependency>
          ????<groupId>redis.clientsgroupId>
          ????<artifactId>jedisartifactId>
          dependency>

          另外,這里再貼一下 Spring Boot 關(guān)于 RedisProperties 的所有配置項

          # REDIS RedisProperties
          spring.redis.cluster.max-redirects= # Maximum number of redirects to follow when executing commands across the cluster.
          spring.redis.cluster.nodes= # Comma-separated list of "host:port" pairs to bootstrap from.
          spring.redis.database=0 # Database index used by the connection factory.
          spring.redis.url= # Connection URL. Overrides host, port, and password. User is ignored. Example: redis://user:[email protected]:6379
          spring.redis.host=localhost # Redis server host.
          spring.redis.jedis.pool.max-active=8 # Maximum number of connections that can be allocated by the pool at a given time. Use a negative value for no limit.
          spring.redis.jedis.pool.max-idle=8 # Maximum number of "idle" connections in the pool. Use a negative value to indicate an unlimited number of idle connections.
          spring.redis.jedis.pool.max-wait=-1ms # Maximum amount of time a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely.
          spring.redis.jedis.pool.min-idle=0 # Target for the minimum number of idle connections to maintain in the pool. This setting only has an effect if it is positive.
          spring.redis.lettuce.pool.max-active=8 # Maximum number of connections that can be allocated by the pool at a given time. Use a negative value for no limit.
          spring.redis.lettuce.pool.max-idle=8 # Maximum number of "idle" connections in the pool. Use a negative value to indicate an unlimited number of idle connections.
          spring.redis.lettuce.pool.max-wait=-1ms # Maximum amount of time a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely.
          spring.redis.lettuce.pool.min-idle=0 # Target for the minimum number of idle connections to maintain in the pool. This setting only has an effect if it is positive.
          spring.redis.lettuce.shutdown-timeout=100ms # Shutdown timeout.
          spring.redis.password= # Login password of the redis server.
          spring.redis.port=6379 # Redis server port.
          spring.redis.sentinel.master= # Name of the Redis server.
          spring.redis.sentinel.nodes= # Comma-separated list of "host:port" pairs.
          spring.redis.ssl=false # Whether to enable SSL support.
          spring.redis.timeout= # Connection timeout.

          3.3、自定義一個 RedisTemplate

          這個看你自己,不自定義也不影響使用,只是說可能不那么順手,所以阿粉習(xí)慣自定義一個。因為 Spring BootRedisAutoConfiguration 中默認(rèn)配置了 RedisTemplateStringRedisTemplate兩個模板類,然而RedisTemplate并未指定keyvalue的序列化器。

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

          3.4、Person 實(shí)體類

          聲明一個 Person 實(shí)體類:

          /**
          ?*?@author?:created by mmzsblog
          ?*?@date?:created at 2020/06/23 16:41
          ?*/

          @Data
          @NoArgsConstructor
          @AllArgsConstructor
          public?class?Person?implements?Serializable?{

          ????private?static?final?long?serialVersionUID?=?-8183942491930372236L;
          ????private?Long?userId;
          ????private?String?username;
          ????private?String?password;
          }

          3.5、測試

          通過編寫一個 UserController 來進(jìn)行測試:

          @RestController
          public?class?UserController?{
          ????@Resource
          ????private?RedisTemplate?redisTemplate;

          ????@Resource
          ????private?StringRedisTemplate?stringRedisTemplate;

          ????@GetMapping("/set")
          ????public?String?set()?{
          ????????stringRedisTemplate.opsForValue().set("one",?"1");
          ????????
          ????????// redisTemplate 保存的是字節(jié)序列,因為 RestTemplateConfig 自定義的時候指定了 key 和 value 的序列化器。
          ????????redisTemplate.opsForValue().set("two",?"2");
          ????????redisTemplate.opsForValue().set("person",?new?Person(1L,?"luffy",?"123456789"));

          ????????//?測試線程安全
          ????????ExecutorService?executorService?=?Executors.newFixedThreadPool(1000);
          ????????IntStream.range(0,?1000).forEach(i?->?{
          ????????????executorService.execute(()?->?stringRedisTemplate.opsForValue().increment("num",?1));
          ????????});
          ????????return?"Ok!";
          ????}

          ????@GetMapping("/get")
          ????public?String?get()?{
          ????????String?one?=?stringRedisTemplate.opsForValue().get("one");
          ????????if?("1".equals(one))?{
          ????????????System.out.println("key:?one"?+?"?||?value:?"?+?one);
          ????????}

          ????????Object?two?=?redisTemplate.opsForValue().get("two");
          ????????if?("2".equals(two.toString()))?{
          ????????????System.out.println("key:?two"?+?"?||?value:?"?+?two);
          ????????}

          ????????Person?user?=?(Person)?redisTemplate.opsForValue().get("person");
          ????????if?("luffy".equals(user.getUsername()))?{
          ????????????System.out.println("key:?person"?+?"?||?value:?"?+?user);
          ????????}
          ????????return?"Ok!";
          ????}
          }

          用RedisDesktopManager工具查看,數(shù)據(jù)如下:

          StringRedisTemplate 設(shè)置的鍵值是String類型的:

          RedisTemplate 設(shè)置的鍵值是二進(jìn)制的字節(jié)流形式存儲的,從截圖中的 [Binary] 標(biāo)識符也能看出:

          自定義的 RedisTemplateStringRedisTemplate 并不會有什么沖突,想用 String 存儲還是二進(jìn)制的字節(jié)流形式存儲完全取決于你自己。

          參考

          • https://lettuce.io/
          • Spring Boot官方文檔 91.4
          • 《Redis深度歷險:核心原理和應(yīng)用實(shí)踐》
          • http://blog.battcn.com/2018/05/11/springboot/v2-nosql-redis/
          • https://www.jianshu.com/p/f7d11e7109b7


          < END >



          瀏覽 63
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  理伦一区| 网红操逼视频在线观看免费视频在线观看 | 日本国产视频 | 久久才是精品 | 日韩精品av在线 日韩精品一级毛斤 |