Quarkus框架实践 - redis-client

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

前言

如果要使用quarkus 的native image 本地编译,使用spring等的redisclient 都可能导致一些难以解决的问题。那么取而代之的就是quarkus-redis-client了,本文将简单的讨论一下如何使用quarkus-redis-client作为缓存的方法。在这篇文章中,我们将实现redis客户端的 GETSETDEL 和 KEYS等简单操作的方法,并且给我们上文的天气预报响应式方法加上缓存。

配置和依赖

quarkus有关的部分依赖都已经在前文中有展示。这里在maven中先引入quarkus-redis-client

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-redis-client</artifactId>
</dependency>
复制代码

然后在配置的properties中加入 redis的配置

quarkus.redis.hosts=redis://localhost:6379
quarkus.redis.database=0
quarkus.redis.timeout=10s
复制代码

然后编写redisService,使得使用更加接近传统的redis 客户端服务。

@ApplicationScoped
public class RedisClientService  {

    @Inject
    RedisClient redisClient;
    @Inject
    ReactiveRedisClient reactiveRedisClient;


public String get(String key) {
    Response response = redisClient.get(key);
    return response == null ? null : response.toString();

}


void set(String key, String value) {
    redisClient.set(Arrays.asList(key, value.toString()));
}

Uni<JsonArray> result =
        // Step 1 - 获得key
        reactiveRedisClient.keys("*")
                .onItem().transformToMulti(keys -> Multi.createFrom().iterable(keys))
                .onItem().castTo(String.class)
                // Step 2 - 检索相关对象对于每一个key
                .onItem().transformToUniAndMerge(key -> reactiveRedisClient.hgetall(key))
                // Step 3 and 4 - 生成包含所有对象的JsonArray
                .collect().in(JsonArray::new, JsonArray::add);

复制代码

在Quarkus的redis client中存在两个类型的客户端,一个是RedisClient,一个是ReactiveRedisClientRedisClient支持传统型的增删改查,ReactiveRedisClient是Quarkus编写的更适合响应式编程的方法。 举个例子,如果想要实现一种redis使用方式:

1.从Redis获取所有密钥
2.对于每个键->检索相关对象
3.将此对象添加到JsonArray
4.生成包含所有对象的JsonArray
复制代码

如何不增加大量的业务代码就能简单有效的实现这样的效果。直接通过ReactiveRedisClient返回的Uni就可以:

Uni<JsonArray> result =
  // Step 1 - 获得key
  reactiveRedisClient.keys("*")
    .onItem().transformToMulti(keys -> Multi.createFrom().iterable(keys))
    .onItem().castTo(String.class)
  // Step 2 - 检索相关对象对于每一个key
    .onItem().transformToUniAndMerge(key -> redis.hgetall(key))
  // Step 3 and 4 - 生成包含所有对象的JsonArray
    .collect().in(() -> new JsonArray(), (arr, obj) -> arr.add(obj));
复制代码

Quarkus中的响应式代码设计让很多业务逻辑和计算的实现大大的简化了。

这里我们使用原有的代码逻辑获取天气,并且将天气缓存到redis的客户端中

public Uni<Weather> testCache( String name) {
    Weather dto = null;
    if(null!=redisClientService.get(name)){
        dto= JSONObject.parseObject(redisClientService.get(name), Weather.class);
        return   Uni.createFrom().item(dto);
    }
    String code= cityService.getCode(name);
    try {
        dto = JSONObject.parseObject(restClient.getStream(code), Weather.class);
    } catch (IOException e) {
        e.printStackTrace();
    }
    redisClientService.set(name,JSONObject.toJSONString(dto));
    return   Uni.createFrom().item(dto);
}
复制代码

默认redis已经安装好了在机器上,使用brew services start redis启动redis的服务器。

使用 $ mvn quarkus:dev启动调试模式,第一次执行是没有缓存,直接调用网络接口 屏幕快照 2022-04-15 上午12.03.15.png

然后再次调用就快了很多倍

屏幕快照 2022-04-15 上午12.05.04.png

再简单的做个对比 同时调用150次,不同的城市,缓存和接口的速度对比,首先使用接口 :

private static String[] cityNames = new String[]{"北京", "上海", "广州", "深圳", "南京"};

private static int[] cityTimes = new int[]{50, 40, 30, 20, 10};
复制代码

调用结果如下

屏幕快照 2022-04-15 上午12.51.05.png 总计10685ms

使用缓存的版本:

屏幕快照 2022-04-15 上午12.53.35.png 总计 1478ms

考虑到各种因素,缓存大概能加速整个查询的过程10倍。

参考

quarkus.io/guides/redi… quarkus.io/blog/mutiny…

猜你喜欢

转载自juejin.im/post/7086504587347099678