Docker安裝Redis,Spring Boot使用Redis,解決Redis發(fā)生的類型轉(zhuǎn)換異常

Docker安裝Redis(如果已安裝請?zhí)^這一步)

1、拉取Redis鏡像(默認(rèn)最新版本)

docker pull redis

如果下載比較慢的話建議配置阿里云鏡像

查看阿里云鏡像:阿里云官網(wǎng)-->產(chǎn)品-->搜索容器鏡像服務(wù)-->管理控制臺

image-20201107195729430

左側(cè)邊欄下方的鏡像加速器:

image-20201107195935790

點(diǎn)進(jìn)去可以看到下方有一個加速地址和使用方法:

image-20201107200357499

把大括號及大括號里的內(nèi)容復(fù)制進(jìn)/etc/docker/daemon.json文件中:

vim /etc/docker/daemon.json

重新加載daemon文件和docker即添加鏡像成功

systemctl daemon-reload

systemctl restart docker

2、安裝完redis鏡像后查看是否安裝成功

docker images

3、運(yùn)行redis

docker run -d -p 6379:6379 --name myredis redis

4、查看是否運(yùn)行成功

docker ps

快速使用Redis

1、導(dǎo)入Redis的依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、添加配置文件

# Redis數(shù)據(jù)庫索引(默認(rèn)為0)
spring.redis.database=0  
# Redis服務(wù)器地址(默認(rèn)為localhost)
spring.redis.host=localhost
# Redis服務(wù)器連接端口(默認(rèn)為6379)
spring.redis.port=6379  
# Redis服務(wù)器連接密碼(默認(rèn)為空)
spring.redis.password=
# 連接池最大連接數(shù)(使用負(fù)值表示沒有限制) 默認(rèn) 8
spring.redis.lettuce.pool.max-active=8
# 連接池最大阻塞等待時間(使用負(fù)值表示沒有限制) 默認(rèn) -1
spring.redis.lettuce.pool.max-wait=-1
# 連接池中的最大空閑連接 默認(rèn) 8
spring.redis.lettuce.pool.max-idle=8
# 連接池中的最小空閑連接 默認(rèn) 0
spring.redis.lettuce.pool.min-idle=0

3、添加Redis配置類

自定義一個RedisCacheManager

@Configuration
public class MyRedisConfig {
    @Bean
    public RedisCacheManager defaultRedisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration cacheConfiguration =
                RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(Duration.ofHours(6))   // 設(shè)置緩存過期時間為6小時
                        .disableCachingNullValues()     // 禁用緩存空值,不緩存null校驗(yàn)
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new
                                GenericJackson2JsonRedisSerializer()));     // 設(shè)置CacheManager的值序列化方式為json序列化
        return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build();     // 設(shè)置默認(rèn)的cache組件
    }
}

4、開啟基于注解的緩存:@EnableCaching

@EnableCaching
@SpringBootApplication
public class BlogApplication {

   public static void main(String[] args) {
      SpringApplication.run(BlogApplication.class, args);
   }

}

5、使用@Cacheable注解進(jìn)行緩存

@Cacheable主要針對方法配置,能夠根據(jù)方法的請求參數(shù)對其結(jié)果進(jìn)行緩存

@Service
public class BlogServiceImpl implements BlogService {

    @Autowired
    private BlogMapper blogMapper;
    
    @Cacheable(cacheNames = "totalBlog")
    @Override
    public Long getTotalBlogs() {
        return blogMapper.getTotalBlogs();
    }
}

原理:

  1. 方法運(yùn)行之前,先去查詢Cache(緩存組件),按照cacheNames指定的名字獲取
  2. 沒有查到緩存就調(diào)用目標(biāo)方法,并將目標(biāo)方法的返回的結(jié)果放進(jìn)緩存中
  3. 查到了緩存就直接使用緩存,就不會再去數(shù)據(jù)庫查詢數(shù)據(jù)

執(zhí)行完以上步驟即使用完成。

踩過的坑:反序列化獲取數(shù)據(jù)發(fā)生類型轉(zhuǎn)換異常

往Redis中存儲Long類型的數(shù)據(jù)時,反序列化時發(fā)生Integer轉(zhuǎn)Long類型轉(zhuǎn)換異常;

image-20201108201649783

我明明存的是Long類型的數(shù)據(jù)啊,怎么存進(jìn)去就變成Integer類型了呢?

這要從自定義CacheManager說起......

@Configuration
public class MyRedisConfig {
    @Bean
    public RedisCacheManager defaultRedisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration cacheConfiguration =
                RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(Duration.ofHours(6))   // 設(shè)置緩存過期時間為6小時
                        .disableCachingNullValues()     // 禁用緩存空值,不緩存null校驗(yàn)
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new
                                GenericJackson2JsonRedisSerializer()));     // 設(shè)置CacheManager的值序列化方式為json序列化
        return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build();     // 設(shè)置默認(rèn)的cache組件
    }

}

我們自定義CacheManager的時候,使用的是GenericJackson2JsonRedisSerializer序列化器,而GenericJackson2JsonRedisSerializer在反序列化的時候會統(tǒng)一將緩存反序列化為Object類型,又因?yàn)槲覀兇娴闹凳切∮?code>Integer.MAX_VALUE的,自然而然的就轉(zhuǎn)為了Integer。

而我們要解決這種情況的話,只有在存數(shù)據(jù)的時候就指定數(shù)據(jù)類型,可以使用Jackson2JsonRedisSerializer

@Bean
public RedisCacheManager longRedisCacheManager(RedisConnectionFactory redisConnectionFactory) {
    RedisCacheConfiguration cacheConfiguration =
            RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofHours(6))   // 設(shè)置緩存過期時間為6小時
                    .disableCachingNullValues()     // 禁用緩存空值,不緩存null校驗(yàn)
                    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new
                            Jackson2JsonRedisSerializer<Long>(Long.class)));     // 設(shè)置CacheManager的值序列化方式為json序列化,指定我們所存的數(shù)據(jù)為Long類型,取出時自然會幫我們反序列化成Long類型
    return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build();     // 設(shè)置默認(rèn)的cache組件
}

當(dāng)存在兩個或兩個以上的RedisCacheManager的時候,我們必須在某個RedisCacheManager上標(biāo)注@Primary注解,來表示這個RedisCacheManager是主要的;當(dāng)然在使用緩存注解來進(jìn)行緩存的時候,如果需要使用指定的RedisCacheManager,就可以使用cacheManager屬性進(jìn)行指定,如果沒有指定,就默認(rèn)使用標(biāo)注了@Primary注解的RedisCacheManager

@Cacheable(cacheNames = "totalBlog",cacheManager = "longRedisCacheManager")
@Override
public Long getTotalBlogs() {
    return blogMapper.getTotalBlogs();
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容