Spring Boot 之 整合Redis

整合Redis

NoSQL是指非关系型数据库,非关系型数据库和关系型数据库两者存在许多显著的不同点,其中最重要的是NoSQL不使用SQL作为查询语言。其数据存储可以不需要固定的表格模式,一般都有水平可扩展性的特征。NoSQL主要有如下几种不同的分类:

  • Key/Value键值存储。这种数据存储通常都是无数据结构的,一般被当作字符串或者二进制数据,但是数据加载速度快,典型的使用场景是处理高并发或者用于日志系统等,这一类的数据库有Redis、Tokyo Cabinet等。
  • 列存储数据库。列存储数据库功能相对局限,但是查找速度快,容易进行分布式扩展,一般用于分布式文件系统中,这一类的数据库有HBase、Cassandra等。
  • 文档型数据库。和Key/Value键值存储类似,文档型数据库也没有严格的数据格式,这既是缺点也是优势,因为不需要预先创建表结构,数据格式更加灵活,一般可用在Web应用中,这一类数据库有MongoDB、CouchDB等。
  • 图形数据库。图形数据库专注于构建关系图谱,例如社交网络,推荐系统等,这一类的数据库有Neo4J、DEX等。

NoSQL种类繁多,Spring Boot对大多数NoSQL都提供了配置支持。

1. Redis简介

Redis是一个使用C编写的基于内存的NoSQL数据库,它是目前最流行的键值对存储数据库。Redis 由一个Key、Value映射的字典构成,与其他NoSQL 不同,Redis 中 Value的类型不局限于字符串,还支持列表、集合、有序集合、散列等。Redis不仅可以当作缓存使用,也可以配置数据持久化后当作 NoSQL 数据库使用,目前支持两种持久化方式:快照持久化和AOF 持久化。另一方面,Redis也可以搭建集群或者主从复制结构,在高并发环境下具有高可用性。

2. Redis安装

我用的是宝塔面板进行安装就不详细介绍了

3. 配置Redis

Redis安装成功后,接下来进行配置,打开Redis,解压目录下的redis.conf文件,主要修改如下几个地方:

daemonizeyes
#bind 127.0.0.1
requirepass 123@456
protected-mode no

配置解释:

  • 第1行配置表示允许Redis在后台启动。
  • 第2行配置表示允许连接该Redis实例的地址,默认情况下只允许本地连接,将默认配置注释掉,外网就可以连接Redis了。
  • 第3行配置表示登录该Redis实例所需的密码。
  • 由于有了第3行配置的密码登录,因此第4行就可以关闭保护模式了。

4.配置CentOs

为了能够远程连接上Redis,还需要关闭CentOS防火墙,执行如下命令:

systemctl stop firewalld.service
systemctl disable firewalld.service

其中,第1行表示关闭防火墙,第2行表示禁止防火墙开机启动。

如果使用宝塔面板可以直接放行6379端口号,也可以放行.还有

5. Redis启动与关闭

最后,执行如下命令启动Redis:

redis-server redis.conf

Redis启动成功后,再执行如下命令进入Redis控制台,其中-a表示Redis登录密码:

redis-cli -a 123@456

进入控制台后执行ping 命令,如果能看到PONG,表示Redis 安装成功,如图6-1所示。如果想关闭Redis实例,可以在控制台执行SHUTDOWN,然后使用exit退出,或者直接在命令行执行如下命令:

redis-cli -p 6379 -a 1230456 shutdown

至此,Redis就安装并启动成功了。记得后面要关闭外网访问权限,不然redis容易受到外网攻击。

6. 整合Spring Boot

Redis的Java客户端有很多,例如Jedis.JRedis.Spring Data Redis等, Spring Boot借助于SpringData Redis为 Redis提供了开箱即用自动化配置,开发者只需要添加相关依赖并配置Redis连接信息即可,具体整合步骤如下。

6.1 创建Spring Boot 项目

首先创建Spring Boot Web项目,添加如下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

默认情况下,spring-boot-starter-data-redis使用的Redis 工具是Lettuce,考虑到有的开发者习惯使用Jedis,因此可以从spring-boot-starter-data-redis中排除Lettuce并引入Jedis,修改为如下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

6.2 配置Redis

接下来在application.properties 中配置Redis连接信息,代码如下:

spring.redis.database=0
spring.redis.host=120.55.61.170
spring.redis.port=6379
spring.redis.password=123@456
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.max-wait=-1ms
spring.redis.jedis.pool.min-idle=0

配置解释:

  • 第14行是基本连接信息配置,第58行是连接池信息配置。
  • 第1行配置表示使用的Redis库的编号,Redis中提供了16个database,编号为0~15。第2行配置表示Redis 实例的地址。
  • 第3行配置表示Redis端口号,默认是6379。第4行配置表示Redis登录密码。
  • 第5行配置表示Redis连接池的最大连接数。
  • 第6行配置表示Redis连接池中的最大空闲连接数。
  • 第7行配置表示连接池的最大阻塞等待时间,默认为-1,表示没有限制。第8行配置表示连接池最小空闲连接数。
  • 如果项目使用了Lettuce,则只需将第5~8行配置中的jedis修改为lettuce 即可。

在Spring Boot的自动配置类中提供了RedisAutoConfiguration进行Redis 的配置,部分源码如

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(name = "redisTemplate")
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
		return new StringRedisTemplate(redisConnectionFactory);
	}

}

由这一段源码可以看到,application.properties中配置的信息将被注入RedisProperties中,如果开发者自己没有提供RedisTemplate或者StringRedisTemplate实例,则 Spring Boot默认会提供这两个实例,RedisTemplate和 StringRedisTemplate实例则提供了Redis 的基本操作方法。

6.3 创建实体类

创建一个Book类,代码如下:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book implements Serializable {
    private Integer id;
    private String name;
    private String author;
}

6.4 创建Controller

创建BookController进行测试:

@RestController
public class BookController {
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    RedisTemplate redisTemplate;

    @RequestMapping("/test1")
    public void test1() {
        ValueOperations<String, String> ops1 = stringRedisTemplate.opsForValue();
        ops1.set("name", "三国演义");
        String name = ops1.get("name");
        System.out.println(name);
        ValueOperations ope2 = redisTemplate.opsForValue();
        Book book = new Book();
        book.setId(1);
        book.setName("红楼梦");
        book.setAuthor("曹雪芹");
        ope2.set("b1", book);
        Book book1 = (Book) ope2.get("b1");
        System.out.println(book1);
    }
}

代码解释:

  • StringRedisTemplate是RedisTemplate的子类,StringRedisTemplate中的key和value都是字符串,采用的序列化方案是StringRedisSerializer,而 RedisTemplate则可以用来操作对象,RedisTemplate采用的序列化方案是JdkSerializationRedisSerializer。无论是StringRedisTemplate还是RedisTemplate,操作Redis 的方法都是一致的。
  • StringRedisTemplate和RedisTemplate都是通过opsForValue、opsForZSet或者opsForSet等方法首先获取一个操作对象,再使用该操作对象完成数据的读写。
  • 第11行向Redis中存储一条记录,第12行将之读取出来。第19行向Redis中存储一个对象,第20行将之读取出来。

6.5测试

在浏览器中输入http://localhost:8080/testl,可看到控制打印日志。

三国演义
Book(id=1, name=红楼梦, author=曹雪芹)

7. Redis集群整合Spring Boot

前文向读者介绍了单个Redis实例整合Spring Boot,在实际项目中,开发者为了提高Redis的扩展性,往往需要搭建Redis集群,这样就会涉及Redis集群整合Spring Boot,接下来看看这个问题。

7.1搭建Redis集群

  1. 集群原理
    在Redis集群中,所有的Redis节点彼此互联,节点内部使用二进制协议优化传输速度和带宽。当一个节点挂掉后,集群中超过半数的节点检测失效时才认为该节点已失效。不同于Tomcat集群需要使用反向代理服务器,Redis集群中的任意节点都可以直接和 Java客户端连接。Redis集群上的数据分配则是采用哈希槽(HASH SLOT),Redis集群中内置了16384个哈希槽,当有数据需要存储时,Redis 会首先使用CRC16算法对key进行计算,将计算获得的结果对16384取余,这样每一个key都会对应一个取值在0~16383之间的哈希槽,Redis则根据这个余数将该条数据存储到对应的Redis节点上,开发者可根据每个Redis实例的性能来调整每个Redis实例上哈希槽的分布范围。
  2. 集群规划
    本案例在同一台服务器上用不同的端口表示不同的Redis服务器(伪分布式集群)。
    主节点:8001,8002,8003,8007。
    从节点:8004,8005,8006,8008。

建搭建Redis集群在其他文章专门介绍过,就不介绍了

7.2 配置 Spring Boot

不同于单机版Redis 整合Spring Boot,Redis集群整合Spring Boot需要开发者手动配置,配置步骤如下。

7.2.1 创建Spring Boot项目

首先创建一个 Spring Boot Web项目,添加如下依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
        <version>2.11.1</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
        <!--去除Lettuce-->
        <exclusions>
            <exclusion>
                <groupId>io.lettuce</groupId>
                <artifactId>lettuce-core</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
</dependencies>
7.2.2 配置集群信息

由于集群节点有多个,可以保存在一个集合中,因此这里的配置文件使用YAML格式的,删除resources目录下的 application.properties文件,创建application.yml配置文件,文件内容如下:

spring:
  redis:
    cluster:
      ports:
        - 7001
        - 7002
        - 7003
        - 7004
        - 7005
        - 7006
        - 7007
        - 7008
      host: 120.55.61.170
      poolConfig:
        max-total: 8
        max-idle: 8
        max-wait-millis: -1
        min-idle: 0

由于本案例Redis实例的 host 都是一样的,因此这里配置了一个host,而port配置成了一个集合,这些port将被注入一个集合中。poolConfig 则是基本的连接池信息配置。

7.2.3 配置Redis

创建RedisConfig,完成对Redis 的配置,代码如下:

@Configuration
@ConfigurationProperties("spring.redis.cluster")
public class RedisConfig {
    List<Integer> ports;
    String host;
    JedisPoolConfig poolConfig;

    public List<Integer> getPorts() {
        return ports;
    }

    public void setPorts(List<Integer> ports) {
        this.ports = ports;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public JedisPoolConfig getPoolConfig() {
        return poolConfig;
    }

    public void setPoolConfig(JedisPoolConfig poolConfig) {
        this.poolConfig = poolConfig;
    }

    @Bean
    RedisClusterConfiguration redisClusterConfiguration() {
        RedisClusterConfiguration configuration = new RedisClusterConfiguration();
        List<RedisNode> nodes = new ArrayList<>();
        for (Integer port : ports) {
            nodes.add(new RedisNode(host, port));
        }
        configuration.setClusterNodes(nodes);
        return configuration;
    }


    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        JedisConnectionFactory factory = new
                JedisConnectionFactory(redisClusterConfiguration(), poolConfig);
        return factory;
    }

    @Bean
    RedisTemplate redisTemplate() {
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(jedisConnectionFactory());
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        return redisTemplate;
    }

    @Bean
    StringRedisTemplate stringRedisTemplate() {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(jedisConnectionFactory());
        stringRedisTemplate.setKeySerializer(new StringRedisSerializer());
        stringRedisTemplate.setKeySerializer(new StringRedisSerializer());
        return stringRedisTemplate;
    }
}

代码解释:

  • 通过@ConfigurationProperties注解声明配置文件前缀,配置文件中定义的ports 数组、host 以及连接池配置信息都将被注入port、host、poolConfig 三个属性中。

  • 配置RedisClusterConfiguration实例,设置Redis登录密码以及Redis节点信息。

  • 根据 RedisClusterConfiguration实例以及连接池配置信息创建 Jedis连接工厂JedisConnectionFactory。

  • 根据JedisConnectionFactory创建RedisTemplate和StringRedisTemplate,同时配置key和 value的序列化方式。有了RedisTemplate和StringRedisTemplate,剩下的用法就和单实例的用法一致了。

7.2.4 创建Controller

创建Controller和 Book 实例,代码如下:

@RestController
public class BookController {
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    RedisTemplate redisTemplate;

    @RequestMapping("/test1")
    public void test1() {
        ValueOperations ops = redisTemplate.opsForValue();
        Book book = new Book();
        book.setName("红楼梦");
        book.setAuthor("曹雪芹");
        ops.set("b1", book);
        System.out.println(ops.get("b1"));
        ValueOperations<String, String> ops2 = stringRedisTemplate.opsForValue();
        ops2.set("k1", "v1");
        System.out.println(ops2.get("k1"));
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book implements Serializable {
    private String name;
    private String author;
}

测试Controller 与单实例Redis测试Controller基本一致。创建完成后,启动Spring Boot项目。

7.2.4 测试

最后,在浏览器中输入 http://localhost:8080/test1,控制台打印日志。

Book(name=红楼梦, author=曹雪芹)
v1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值