spring boot 1.5.9 整合redis

上一篇博客:spring boot 1.5.4 集成Swagger2構建Restful API(十八)

Redis是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫。

redis官網:https://redis.io/

redis中文網:http://www.redis.net.cn/

書籍參閱:《redis實戰》

redis概述

Redis可以存儲鍵與5種不同數據結構類型之間的映射,這5種數據結構類型分別爲
STRING(字符串)、LIST(列表)、SET(集合)、HASH(散列)和ZSET(有序集合)
有一部分Redis命令對於這5種結構都是通用的,如DEL、TYPE、RENAME等;但也有一部分Redis命令只能對特定的一種或者兩種結構使用;

一些數據庫和緩存服務器的特性與功能


名稱 類型 數據存儲選項 查詢類型 附加功能
Redis 使用內存存儲(in-memory)的非關係數據庫 字符串、列表、集合、散列表、有序集合 每種數據類型都有自己的專屬命令,另外還有批量操作(bulk operation)和不完全(partial)的事務支持 發佈與訂閱,主從複製(master/slave replication),持久化,腳本(存儲過程,stored procedure)
memcached 使用內存存儲的鍵值緩存 鍵值之間的映射 創建命令、讀取命令、更新命令、刪除命令以及其他幾個命令 爲提升性能而設的多線程服務器
MySQL 關係數據庫 每個數據庫可以包含多個表,每個表可以包含多個行;可以處理多個表的視圖(view);支持空間(spatial)和第三方擴展 SELECT、 INSERT、 UPDATE、 DELETE、函數、存儲過程 支持ACID性質(需要使用InnoDB),主從複製和主主複製 (master/master replication)
PostgreSQL 關係數據庫 每個數據庫可以包含多個表,每個表可以包含多個行;可以處理多個表的視圖;支持空間和第三方擴展;支持可定製類型 SELECT、 INSERT、 UPDATE、 DELETE、內置函數、自定義的存儲過程 支持ACID性質,主從複製,由第三方支持的多主複製(multi-master replication)
MongoDB 使用硬盤存儲(on-disk)的非關係文檔存儲 每個數據庫可以包含多個表,每個表可以包含多個無schema(schema-less)的BSON文檔 創建命令、讀取命令、更新命令、刪除命令、條件查詢命令等 支持map-reduce操作,主從複製,分片,空間索引(spatial index)

==表格樣式不是我能決定的,湊合看吧==

Redis提供的5種結構


結構類型 結構存儲的值 結構的讀寫能力
STRING 可以是字符串、整數或者浮點數 對整個字符串或者字符串的其中一部分執行操作;對整數和浮點數執行自增(increment)或者自減(decrement)操作
LIST 一個鏈表,鏈表上的每個節點都包含了一個字符串 從鏈表的兩端推入或者彈出元素;根據偏移量對鏈表進行修剪(trim);讀取單個或者多個元素;根據值查找或者移除元素
SET 包含字符串的無序收集器(unordered collection),並且被包含的每個字符串都是獨一無二、各不相同的 添加、獲取、移除單個元素;檢查一個元素是否存在於集合中;計算交集、並集、差集;從集合裏面隨機獲取元素
HASH 包含鍵值對的無序散列表 添加、獲取、移除單個鍵值對;獲取所有鍵值對
ZSET(有序集合) 字符串成員(member)與浮點數分值(score)之間的有序映射,元素的排列順序由分值的大小決定 添加、獲取、刪除單個元素;根據分值範圍(range)或者成員來獲取元素

redis特性


源碼簡單 ,約23000行C語言源代碼。

  1. 速度快
    Redis是用C語言實現的;Redis的所有數據存儲在內存中,用於快速地讀寫訪問。
  2. 持久化
    Redis的所有數據存儲在內存中,對數據的更新將異步地保存到磁盤上;
    redis的持久化有兩種方式:AOF與RDB兩種模式
  3. 支持多種數據結構
    Redis支持五種數據結構:String、List、Set、Hash、Zset
  4. 支持多種編程語言
    Java、php、Python、Ruby、Lua、Node.js等
  5. 功能豐富
    除了支持五種數據結構之外,還支持緩存、事務、流水線、發佈/訂閱、消息隊列等功能。
    發佈/訂閱模型: Redis支持創建發佈和訂閱通道,這樣Redis客戶端可以訂閱任意的通道來進行數據消費,並且任何已訂閱該通道的客戶端可以發佈數據。
  6. 主從複製
    主服務器(master)執行寫入(增刪改),從(slave)服務器執行查詢。複製提供可伸縮性和可用性。任何一個slave宕機,其他的slave還可以提供數據訪問。
  7. 虛擬內存
    Redis使用RAM作爲內存式存儲。但是,在內存不足的情況下,它使用虛擬內存來保存數據。
  8. 高可用及分佈式
    Redis-Sentinel(v2.8)支持高可用
    Redis-Cluster(v3.0)支持分佈式

redis部分命令

flushdb:清空當前數據庫;
select [index]:選擇索引數據庫,index爲索引值名,如:select 1;
del [key]:刪除一條指定key的值;
keys *:查看數據庫內所有的key;
flushall:清空所有數據庫;
quit:退出客戶端連接。
==友情提示:部分命令慎用,線上一定不能用==

redis安裝

redis下載安裝

  1. windows版本下載:https://github.com/MicrosoftArchive/redis/releases ,目前是redis-3.2.100版本。
    image
  2. 解壓下載的zip壓縮包:
    image
    Redis on Windows.docx:關於Redis的描述文檔
    redis.windeows.conf:默認的配置文件
    RedisService.docx:安裝手冊
    redis-server.exe:redis服務啓動執行文件
    redis-cli.exe:redis客戶端啓動執行文件
  3. 註冊redis服務到本機系統中
    在當前redis解壓文件目錄下...\Redis-x64-3.2.100\,本機系統中註冊服務:

redis-server --service-install redis.windows.conf --loglevel verbose
卸載服務:
redis-server --service-uninstall
啓動Redis:
redis-server.exe
指定配置文件啓動,適用於多個redis數據庫的時候
redis-server.exe redis.windows.conf

停止Redis:
redis-server --service-stop

安裝成功:
image
啓動redis:
iamge

  1. redis客戶端測試
    • 雙擊redis客戶端執行文件:redis-cli.exe
    • 測試:ping
      image

redis桌面可視化工具

redis Java客戶端

redis支持的語言,可在官網查看!重點看下redis的java客戶端jedis:

github地址:https://github.com/xetorthio/jedis

spring boot 整合redis

spring boot整合redis有兩種方式:
其一:使用外部配置,通過jedis技術框架實現;
其二:通過spring boot提供的數據訪問框架Spring Data Redis實現,它是基於Jedis的。

第一種方式,可以參考SSM框架整合jedis進行操作配置;重點是第二種實現方式!

spring data redis

通過spring boot中的redis自動配置類,關於redis自動配置類RedisAutoConfiguration.java

//排除redis自動配置註解
@EnableAutoConfiguration(exclude = RedisAutoConfiguration.class)

查看其源碼:
image

spring boot在Spring Data Redis提供了兩個模板:

  • RedisTemplate
  • StringRedisTemplate

RedisTemplate會使用JdkSerializationRedisSerializer處理數據,這意味着key和value都會通過Java進行序列化。
StringRedisTemplate默認會使用StringRedisSerializer處理數據。

要是操作字符串的話,用StringRedisTemplate就可以滿足。但要是想要存儲一個對象Object,我們就需要使用RedisTemplate,並對key採用String序列化方式,對value採用json序列化方式,這時候就需要對redisTemplate自定義配置,項目源碼片段:

/**
     * 實例化 RedisTemplate 對象
     *
     * @return RedisTemplate
     */
    @Bean
    public RedisTemplate<String, Object> functionDomainRedisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        initDomainRedisTemplate(redisTemplate);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    /**
     * 設置數據存入 redis 的序列化方式
         * </br>redisTemplate 序列化默認使用的jdkSerializeable, 存儲二進制字節碼, 導致key會出現亂碼,所以自定義
         * 序列化類
     *
     * @param redisTemplate
     * @param factory
     */
    private void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        // 使用Jackson2JsonRedisSerialize 替換默認序列化
        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);
        //// string結構的數據,設置value的序列化規則和 key的序列化規則
        //StringRedisSerializer解決key中亂碼問題。//Long類型不可以會出現異常信息;
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //value亂碼問題:Jackson2JsonRedisSerializer
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);

        //設置Hash結構的key和value的序列化方式
        //redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
        //redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
    }

RedisTempalte類API

方  法 子API接口 描  述
opsForValue() ValueOperations<K, V> 操作具有簡單值的條目
opsForList() ListOperations<K, V> 操作具有list值的條目
opsForSet() SetOperations<K, V> 操作具有set值的條目
opsForZSet() ZSetOperations<K, V> 操作具有ZSet值(排序的set)的條目
opsForHash() HashOperations<K, HK, HV> 操作具有hash值的條目
boundValueOps(K) BoundValueOperations<K,V> 以綁定指定key的方式,操作具有簡單值的條目
boundListOps(K) BoundListOperations<K,V> 以綁定指定key的方式,操作具有list值的條目
boundSetOps(K) BoundSetOperations<K,V> 以綁定指定key的方式,操作具有set值的條目
boundZSet(K) BoundZSetOperations<K,V> 以綁定指定key的方式,操作具有ZSet值(排序的set)的條目
boundHashOps(K) BoundHashOperations<K,V> 以綁定指定key的方式,操作具有hash值的條目

spring boot緩存管理

spring boot集成redis進行數據緩存功能;有兩種實現:
1,通過在代碼中調用redis API實現數據的CRUD;
【參考RedisUtils工具類,該工具類支持redis的其他業務場景】
2,通過在方法上添加緩存註解實現;
【重點介紹,只支持redis作爲緩存管理時使用】

Spring 提供了很多緩存管理器,例如:

  • SimpleCacheManager
  • EhCacheCacheManager
  • CaffeineCacheManager
  • GuavaCacheManager
  • CompositeCacheManager
  • RedisCacheManager Spring Data提供的緩存管理器:RedisCacheManager

在Spring Boot中通過@EnableCaching註解自動化配置合適的緩存管理器(CacheManager),默認情況下Spring Boot根據下面的順序自動檢測緩存提供者:

  • Generic
  • JCache (JSR-107)
  • EhCache 2.x
  • Hazelcast
  • Infinispan
  • Redis
  • Guava
  • Simple

因爲之前已經配置了RedisTemplate了,Spring Boot就無法自動給RedisCacheManager設置RedisTemplate了,所以要自己配置CacheManager。


1, 修改RedisConfig配置類,添加@EnableCaching註解,並繼承CachingConfigurerSupport,重寫CacheManager 方法:

/**
 * 實例化 CacheManager 對象,指定使用RedisCacheManager作緩存管理
 *
 * @return CacheManager
 */
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
    RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
    // 設置緩存過期時間(單位:秒),60秒
    rcm.setDefaultExpiration(120);
    return rcm;
}

Spring提供瞭如下註解來聲明緩存規則:

  • @Cacheable triggers cache population
  • @cacheevict triggers cache eviction
  • @cacheput updates the cache without interfering with the method execution
  • @caching regroups multiple cache operations to be applied on a method
  • @cacheconfig shares some common cache-related settings at class-level
注 解 描 述
@Cacheable 表明Spring在調用方法之前,首先應該在緩存中查找方法的返回值。如果這個值能夠找到,就會返回緩存的值。否則的話,這個方法就會被調用,返回值會放到緩存之中
@cacheput 表明Spring應該將方法的返回值放到緩存中。在方法的調用前並不會 檢查緩存,方法始終都會被調用
@cacheevict 表明Spring應該在緩存中清除一個或多個條目
@caching 這是一個分組的註解,能夠同時應用多個其他的緩存註解
@cacheconfig 可以在類層級配置一些共用的緩存配置

@Cacheable和@cacheput有一些共有的屬性:

屬  性 類  型 描  述
value String[] 要使用的緩存名稱
condition String SpEL表達式,如果得到的值是false的話,不會將緩存應用到方法調用上
key String SpEL表達式,用來計算自定義的緩存key
unless String SpEL表達式,如果得到的值是true的話,返回值不會放到緩存之中

2, 通過註解@Cacheable,對數據進行緩存處理:
代碼片段:

/**
     * 通過緩存註解,添加數據到redis中
     * </br>實現數據緩存!
     * @param cat 對象
     */
    @Cacheable
    @RequestMapping(value = "/getCat/{catId}", method = RequestMethod.GET)
    @ResponseBody
    public Cat add(@PathVariable("catId") int catId){
        return this.catService.getCat(catId);
    }

注意:Cat對象必須實現implements Serializable接口!
啓動訪問:http://127.0.0.1:8066/redis/getCat/1

java.lang.IllegalStateException: No cache could be resolved for 'Builder[public com.wyait.redis.pojo.Cat com.wyait.redis.controller.RedisCacheController.add(int)] caches=[] | key='' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'' using resolver 'org.springframework.cache.interceptor.SimpleCacheResolver@5e67a11d'. At least one cache should be provided per cache operation.
    at org.springframework.cache.interceptor.CacheAspectSupport.getCaches(CacheAspectSupport.java:244) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]

這個錯誤,是由於@Cacheable註解沒有指定緩存名稱導致的。加上value值,再試:

@Cacheable(value = "catCache")

測試訪問成功!多次訪問,走redis緩存。


3, redis緩存key生成策略

鍵的生成策略有兩種,一種是默認策略,一種是自定義策略。

  • ----------------------------默認策略:

    If no params are given, return SimpleKey.EMPTY.
    If only one param is given, return that instance.
    If more the one param is given, return a SimpleKey containing all parameters.

    默認的key是通過KeyGenerator生成的,其默認策略如下:
    1.如果方法沒有參數,則使用0作爲key;
    2.如果只有一個參數的話則使用該參數作爲key;
    3.如果參數多於一個則使用所有參數的hashcode作爲key;

  • ----------------------------自定義策略:
    自定義策略是指我們通過Spring的EL表達式來指定我們的key。這裏的EL表達式可以使用參數以及它們對應的屬性。使用方法參數時我們可以直接使用“#參數名”或者“#p參數index”。

之前在redisTemplate裏設置了template.setKeySerializer(new StringRedisSerializer()),需要key是string類型。也可以使用SpEL表達式生成Key,
(SpEL表達式:http://itmyhome.com/spring/expressions.html
返回結果需要是string類型(比如#root.methodName就是,#root.method不是String),通用辦法是重寫keyGenerator定製Key默認生成策略(按照緩存名稱+id方式生成key,同時確保更新操作的時候,操作的是同一條數據),也可以在使用緩存註解時指定key:

/**
     * 指定key的生成策略
     * @return KeyGenerator
     */
    @Bean public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override public Object generate(Object target, Method method,
                    Object... params) {
                StringBuilder sb = new StringBuilder();
                String[] value = new String[1];
                // sb.append(target.getClass().getName());
                // sb.append(":" + method.getName());
                Cacheable cacheable = method.getAnnotation(Cacheable.class);
                if (cacheable != null) {
                    value = cacheable.value();
                }
                CachePut cachePut = method.getAnnotation(CachePut.class);
                if (cachePut != null) {
                    value = cachePut.value();
                }
                CacheEvict cacheEvict = method.getAnnotation(CacheEvict.class);
                if (cacheEvict != null) {
                    value = cacheEvict.value();
                }
                sb.append(value[0]);
                //獲取參數值
                for (Object obj : params) {
                    sb.append(":" + obj.toString());
                }
                return sb.toString();
            }
        };
    }

注意:
1,在使用緩存註解時,也可以指定統一規則的key
(比如:@Cacheable(value = "catCache", key = "#root.caches[0].name + ':' + #id"));
就可以不走KeyGenerator默認規則;同樣可以實現,更新和查詢都是同一個key的數據;
2,使用註解進行數據緩存,指定數據過期時間需要百度普及下!


4, 更新緩存數據

更新與刪除Redis緩存需要用到@cacheput和@cacheevict。必須保證keyGenerator生成同一個key,否則更新的不是同一條的數據;

/**
     * 更新redis中的緩存數據
     *</br> #root. 是spEL表達式
     * </br>如果參數是個對象,就通過“#對象.變量”獲取到對應的key中需要的值;比如:#cat.id
     * @param id 主鍵
     */
    @CachePut(value = "catCache", key = "#root.caches[0].name + ':' + #id")
    @RequestMapping(value = "/updateCat", method = RequestMethod.POST)
    @ResponseBody
    public Cat update(@RequestParam int id){
        System.out.println("==========請求參數:"+id);
        return this.catService.updateCat(id);
    }

5, 測試//TODO

wyait-redis項目源碼:

github:https://github.com/wyait/project.git
碼雲: https://gitee.com/wyait/springboot1.5.4.git

spring boot系列文章:

spring boot 1.5.4 概述(一)

spring boot 1.5.4 入門和原理(二)

spring boot 1.5.4 之web開發(三)

spring boot 1.5.4 整合JSP(四)

spring boot 1.5.4 集成devTools(五)

spring boot 1.5.4 集成JdbcTemplate(六)

spring boot 1.5.4 集成spring-Data-JPA(七)

spring boot 1.5.4 配置文件詳解(八)

spring boot 1.5.4 統一異常處理(九)

spring boot 1.5.4 定時任務和異步調用(十)

spring boot 1.5.4 整合log4j2(十一)

spring boot 1.5.4 整合 mybatis(十二)

spring boot 1.5.4 整合 druid(十三)

spring boot 1.5.4 之監控Actuator(十四)

spring boot 1.5.4 整合webService(十五)

spring boot 1.5.4 整合redis、攔截器、過濾器、監聽器、靜態資源配置(十六)

spring boot 1.5.4 整合rabbitMQ(十七)

spring boot 1.5.4 集成Swagger2構建Restful API(十八)

spring boot 1.5.9 整合redis(十九)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章