一般的项目中都会使用缓存,如果你的项目是集群的,那么你肯定会使用 redis 来做缓存。 今天给大家讲讲 SpringBoot 如何整合 redis,以及一些常用的用法。示例有:@Cacheable、@CacheEvict、保存、查询、删除、消息订阅发布、id 自增、分布式锁、lua 脚本、哨兵、redis clust ..

【SpringBoot2.x 实战】整合 redis 及常用功能

本贴最后更新于 239 天前,其中的信息可能已经水流花落

一般的项目中都会使用缓存,如果你的项目是集群的,那么你肯定会使用 redis 来做缓存。
今天给大家讲讲 SpringBoot 如何整合 redis,以及一些常用的用法。示例有:@Cacheable、@CacheEvict、保存、查询、删除、消息订阅发布、id 自增、分布式锁、lua 脚本、哨兵、redis cluster 集群。

整体结构

imagepng

pom 配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.cimu</groupId>
	<artifactId>redis</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>redis</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<pool>2.4.2</pool>
        <fastjson-version>1.2.47</fastjson-version>
	</properties>

	<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</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-web</artifactId>
        </dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.16.20</version>
			<scope>compile</scope>
		</dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>


核心代码

RedisConfig 类:配置了 key 生成策略,缓存管理器,不同泛型的 redisTemplate,配置不同的 RedisConnectionFactory。列出部分代码,具体源码可以看文末源码地址。


/**
 * Redis缓存配置类
 */
@Configuration
@EnableRedisRepositories
public class RedisConfig extends CachingConfigurerSupport {
    @Autowired
    private RedisConnectionFactory factory;
    /**
     * 自定义缓存key生成策略
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuffer sb = new StringBuffer();
                sb.append(target.getClass().getName()).append("_");
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append("_").append(obj == null ? "" : obj.toString());
                }
                return sb.toString();
            }
        };
    }

    /**
     * 缓存管理器
     */
    @Bean
    @Primary
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        // 设置缓存有效期一小时
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(1));
        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(factory))
                .cacheDefaults(redisCacheConfiguration).build();
    }

    /**
     * 5分钟失效缓存管理器
     */
    @Bean
    public CacheManager fiveMinutesManager(RedisConnectionFactory factory) {
        // 设置缓存有效期5分钟
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(5));
        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(factory))
                .cacheDefaults(redisCacheConfiguration).build();
    }

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<Serializable, Serializable> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<Serializable, Serializable> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        //设置序列化工具
        setSerializer(template);
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    @ConditionalOnMissingBean(StringRedisTemplate.class)
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(factory);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setValueSerializer(stringRedisSerializer);
        template.setKeySerializer(stringRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    /**
     * 设置序列化工具
     * @param template RedisTemplate
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    private void setSerializer(RedisTemplate template) {
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        template.setDefaultSerializer(jackson2JsonRedisSerializer);//发布订阅的时候,传输对象如果使用@Builder注解,需要实现无参构造函数
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
    }

}

RedisSubListenerConfig 类:配置了发布订阅的相对于的类,监听的通道。

@Configuration
public class RedisSubListenerConfig {
    @Autowired
  RedisPublisher redisPublisher;

  /**
 * 初始化监听器 */  @Bean
  RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
  MessageListenerAdapter listenerAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
  container.setConnectionFactory(connectionFactory);
  container.addMessageListener(listenerAdapter, new ChannelTopic(redisPublisher.getChannel()));
 return container;
  }

    /**
 * 利用反射来创建监听到消息之后的执行方法 */  @Bean
  MessageListenerAdapter listenerAdapter(RedisReceiver redisReceiver) {
        return new MessageListenerAdapter(redisReceiver, "receiveMessage");
  }

}

发布 / 订阅处理的业务类:
imagepng
如图,包里面是发布 / 订阅的代码
RedisPublisher:为发布消息逻辑。
RedisReceiver:为接收消息,在这里可以实现你的业务代码。
MessageHandler:为接口,业务处理的类都要实现该接口。messageType 方法表示支持哪些业务,processMsg 方法为具体的处理方法。不同的业务消息,只要你的消息类中定义了业务类型,并传入相应的业务类型,在 RedisReceiver 中判断支持哪些业务,在获取相应业务的处理类进行处理,具体实现可以看源码。

UserServiceTest 为单元测试类,所有的测试代码都在这里。

ClusterConfigProperties 类为 redis cluster 的节点配置。

配置

application.properties 文件:

#spring.redis.host=127.0.0.1
#spring.redis.database=0
#spring.redis.port=6379
#spring.redis.password=

spring.cache.type=redis
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.min-idle=0
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-wait=10000
#spring.redis.sentinel.master=mymaster
#spring.redis.sentinel.nodes=127.0.0.1:5000,127.0.0.1:5001,127.0.0.1:5002
redis.cluster.nodes=127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381
redis.cluster.maxRedirects=3

脚本

lua.script 目录下是 lua 脚本,lua 的语法可以去官网看看。

源码地址

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:PipeSoloSymWide 等,欢迎大家加入,贡献开源。

    1881 引用 • 3627 回帖 • 587 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    581 引用 • 1195 回帖 • 838 关注
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    133 引用 • 205 回帖 • 813 关注
回帖   
请输入回帖内容...