【SpringBoot】SpringBoot整合Redis 使用Redis

SpringBoot整合Redis


使用Redis数据库

Redis简介

Redis(官网地址:https://redis.io/)是一个非关系型的高性能缓存数据库,使用ANSI C语言开发,是一种Key-Value模式的数据库,以Key-Value的形式存储数据,支持多种value类型,如string(字符串)、list(链表)、set(集合)、zset(sorted set,有序集合)和hash(哈希类型)。

Redis支持多种开发语言,如Java、C/C++、C#、PHP、JavaScript、Perl、Objective-C、Python、Ruby、Erlang等。同时,Redis还支持数据的持久化,不只可以将数据存储在内存中,还可以将数据存储到硬盘内,不需要担心数据的丢失。在性能方面,Redis官方(官网地址:https://redis.io/)提供了这样的数据:读的速度是110 000次/s,写的速度是81 000次/s,是一个真正的高性能数据库。

对于Redis来说,我们可能对它使用的更多的是缓存,毕竟它可以高效地对数据进行操作。其实它还具备很多功能,比如消息队列、发布、订阅消息等。另外,它提供了持久化的方式。Spring Boot使用Redis数据库分为两步:

(1)在pom文件中加入依赖

(2)在配置文件中加入配置

添加redis的起步依赖

在创建项目之前,需要启动Redis。启动Redis后,

在Windows 启动 redis-server.exe redis服务端
在这里插入图片描述

这个项目项目,实在SpringBoot整合Spring Data JPA基础上添加的,
在pom文件中加入Redis依赖

<!-- 配置使用redis启动器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置redis的连接信息

application.properties

在配置文件中配置Redis信息,这里只配置Redis服务地址和端口,嗯。

#Redis

#Redis服务器地址
spring.redis.host=127.0.0.1
spring.redis.port=6379

注入RedisTemplate测试redis操作

从redis中获得数据 数据的形式 json字符串

判断redis中是否存在数据

不存在数据,从数据库拿再放到Redis数据库

将数据在控制台打印

存在,直接缓存拿数据 ,没有在其他的地方拿 。

注入RedisTemplate,用于对Redis缓存进行操作。创建两个方法:Set方法和Get方法,分别用于使用RedisTemplate进行存放数据和取出数据

package cn.liuawen;

import cn.liuawen.domain.User;
import cn.liuawen.repository.UserRepository;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;


@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootJpaApplication.class)
public class RedisTest {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Test
    public void test() throws JsonProcessingException {
        //从redis缓存中获得指定的数据
        String userListData = redisTemplate.boundValueOps("user.findAll").get();
        //如果redis中没有数据的话
        if(null==userListData){
            //查询数据库获得数据
            List<User> all = userRepository.findAll();
            //转换成json格式字符串
            ObjectMapper om = new ObjectMapper();
            userListData = om.writeValueAsString(all);
            //将数据存储到redis中,下次在查询直接从redis中获得数据,不用在查询数据库
            redisTemplate.boundValueOps("user.findAll").set(userListData);
            System.out.println("===============从数据库获得数据===============");
        }else{
            System.out.println("===============从redis缓存中获得数据===============");
        }

        System.out.println(userListData);

    }

}

开始redis没有数据

127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379>

执行一次

===============从数据库获得数据===============
[{"id":1,"username":"菜鸡文","password":"123"},{"id":2,"username":"柳小子","password":"123"}]

在这里插入图片描述

127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> keys *
1) "user.findAll"
127.0.0.1:6379> get user.findAll
"[{\"id\":1,\"username\":\"\xe8\x8f\x9c\xe9\xb8\xa1\xe6\x96\x87\",\"password\":\"123\"},{\"id\":2,\"username\":\"\xe6\x9f\xb3\xe5\xb0\x8f\xe5\xad\x90\",\"password\":\"123\"}]"
127.0.0.1:6379>

redis有数据了

再执行一次test(), 从redis缓存中拿到数据了

在这里插入图片描述

===============从redis缓存中获得数据===============
[{"id":1,"username":"菜鸡文","password":"123"},{"id":2,"username":"柳小子","password":"123"}]
以下是Spring Boot整合Spring Cloud Alibaba Gateway并使用Redis进行缓存的步骤: 1. 创建Spring Boot工程,添加依赖 在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置Redis 在application.properties文件中添加以下配置: ``` spring.redis.host=127.0.0.1 spring.redis.port=6379 ``` 3. 配置Gateway 在application.yml文件中添加以下配置: ``` spring: cloud: gateway: routes: - id: test_route uri: http://localhost:8080 predicates: - Path=/test/** filters: - name: RequestRateLimiter args: key-resolver: "#{@userKeyResolver}" redis-rate-limiter.replenishRate: 1 redis-rate-limiter.burstCapacity: 2 user: rate-limiter: redis: prefix: "rate-limiter" remaining-key: "remaining" reset-key: "reset" ``` 其中: - id:路由ID - uri:目标服务的URL - predicates:路由断言,此处表示只有访问/test/**的请求才会被路由到目标服务 - filters:路由过滤器,此处使用了RequestRateLimiter过滤器,用于限流 4. 编写Redis限流过滤器 在工程中创建一个RedisRatelimiterFilter类,实现GatewayFilter和Ordered接口,并重写filter方法。 ``` @Component public class RedisRatelimiterFilter implements GatewayFilter, Ordered { private final RedisTemplate<String, String> redisTemplate; private final StringRedisTemplate stringRedisTemplate; private final ObjectMapper objectMapper; public RedisRatelimiterFilter(RedisTemplate<String, String> redisTemplate, StringRedisTemplate stringRedisTemplate, ObjectMapper objectMapper) { this.redisTemplate = redisTemplate; this.stringRedisTemplate = stringRedisTemplate; this.objectMapper = objectMapper; } @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String key = "rate-limiter:" + exchange.getRequest().getPath().value(); String remainingKey = key + ":remaining"; String resetKey = key + ":reset"; return redisTemplate.execute(script, Collections.singletonList(remainingKey), "1", "2") .flatMap(result -> { String json = objectMapper.writeValueAsString(result); Map<String, Object> map = objectMapper.readValue(json, Map.class); int remaining = (int) map.get("remaining"); long reset = (long) map.get("reset"); exchange.getResponse().getHeaders().add("X-RateLimit-Remaining", String.valueOf(remaining)); exchange.getResponse().getHeaders().add("X-RateLimit-Reset", String.valueOf(reset)); if (remaining < 0) { exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS); return exchange.getResponse().setComplete(); } return stringRedisTemplate.opsForValue().increment(remainingKey) .flatMap(result2 -> { if (result2.equals(1L)) { stringRedisTemplate.expire(resetKey, Duration.ofMinutes(1)); } return chain.filter(exchange); }); }); } private static final RedisScript<List<Long>> script = RedisScript.of( "local key = KEYS[1]\n" + "local now = tonumber(ARGV[1])\n" + "local rate = tonumber(ARGV[2])\n" + "local capacity = tonumber(ARGV[3])\n" + "local remaining = redis.call('get', key)\n" + "if remaining then\n" + " remaining = tonumber(remaining)\n" + "else\n" + " remaining = capacity\n" + "end\n" + "if remaining == 0 then\n" + " return {0, 0}\n" + "else\n" + " local reset\n" + " if remaining == capacity then\n" + " reset = now + 60\n" + " redis.call('set', key..\":reset\", reset)\n" + " else\n" + " reset = tonumber(redis.call('get', key..\":reset\"))\n" + " end\n" + " local ttl = reset - now\n" + " local ratePerMillis = rate / 1000\n" + " local permits = math.min(remaining, ratePerMillis * ttl)\n" + " redis.call('set', key, remaining - permits)\n" + " return {permits, reset}\n" + "end\n", ReturnType.MULTI, Collections.singletonList("remaining") ); @Override public int getOrder() { return -1; } } ``` 5. 编写KeyResolver 在工程中创建一个UserKeyResolver类,实现KeyResolver接口,并重写resolve方法。 ``` @Component public class UserKeyResolver implements KeyResolver { @Override public Mono<String> resolve(ServerWebExchange exchange) { String userId = exchange.getRequest().getQueryParams().getFirst("userId"); return Mono.justOrEmpty(userId); } } ``` 6. 测试 启动工程,访问http://localhost:8080/test,可以看到返回结果为“Hello, world!”;再次访问http://localhost:8080/test,可以看到返回结果为“Too Many Requests”。 以上就是Spring Boot整合Spring Cloud Alibaba Gateway并使用Redis进行缓存的步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值