热爱技术,追求卓越
不断求索,精益求精

springboot项目redis管道(pipeline)批量执行命令,基于redisson

redis管道技术

Redis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。这样的处理流程是:
– 客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应。
– 服务端处理命令,并将结果返回给客户端。

Redis管道(pipeline)技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。管道技术最显著的优势是提高了redis服务的性能,省去了产生多个请求消耗的时间和资源。

java使用redisson客户端实现管道技术批量执行命令

redisson是一个优秀的开源redis java客户端组件,redisson也提供了批量执行命令的功能RBatch,官方文档可参考:

https://github.com/redisson/redisson/wiki/10.-%E9%A2%9D%E5%A4%96%E5%8A%9F%E8%83%BD#103-%E5%91%BD%E4%BB%A4%E7%9A%84%E6%89%B9%E9%87%8F%E6%89%A7%E8%A1%8C

使用redisson批量执行操作,非常简单,参照官方文档执行即可,在我们的项目中,我们对redisson的RBatch进行了简单的封装,如下的Batch类(这是一个内部类,redisson是在其文件中定义的)的部分代码:

/**
 * redisson批量执行
 *
 */
public static class Batch{
    /**redisson批量*/
    private RBatch batch;
    /**批量操作选项*/
    private BatchOptions options = BatchOptions.defaults();

    private Batch(){
        batch = redisson.createBatch(options);
    }

    /**
     * 构造方法
     * @param skipResult 是否忽略执行结果
     * @param timeout 执行命令超时时间,单位毫秒
     */
    private Batch(boolean skipResult, long timeout){
        if(skipResult){
            options.skipResult();
        }
        options.responseTimeout(timeout, TimeUnit.MILLISECONDS);
        batch = redisson.createBatch(options);
    }

    /**
     * 默认静态构造
     * @return
     */
    public static Batch of(){
        return new Batch();
    }

    /**
     * 静态构造
     *@param skipResult 是否忽略执行结果
     * @param timeout 执行命令超时时间,单位毫秒
     * @return
     */
    public static Batch of(boolean skipResult, long timeout){
        return new Batch(skipResult, timeout);
    }

    /**
     * 存入redis
     * @param key
     * @param value
     * @return
     */
    public <V> Batch set(String key, V value){
        RBucketAsync<V> bucket = batch.getBucket(key);
        bucket.setAsync(value);
        return this;
    }

    /**
     * 删除key,针对redis的String数据结构操作
     * @param key
     * @return
     */
    public <V> Batch del(String key){
        RBucketAsync<V> bucket = batch.getBucket(key);
        bucket.deleteAsync();
        return this;
    }

    /**
     * 缓存中添加元素,设置过期时间,如expiryTime不满足要求则使用默认时间
     * 
     * @param key
     * @param element
     * @param expiryTime
     */
    public <T> Batch addToSet(String key, T element, Date expiryTime) {
        RSetCacheAsync<T> set = batch.getSetCache(key);
        Date now = new Date();
        long expiry = expiryTime.getTime() - now.getTime();
        expiry = expiry > 0 ? expiry : DEFAULT_CACHE_MILLISECONDS;
        set.addAsync(element, expiry, TimeUnit.MILLISECONDS);
        return this;
    }

    /**
     * 从集合中移除元素
     * 
     * @param key
     * @param element
     */
    public <T> Batch removeFromSet(String key, T element) {
        RSetCacheAsync<T> set = batch.getSetCache(key);
        set.removeAsync(element);
        return this;
    }

    /**
     * 清除整个集合
     * 
     * @param key
     */
    public <T> Batch clearSet(String key) {
        RSetCacheAsync<T> set = batch.getSetCache(key);
        set.deleteAsync();
        return this;
    }

    /**
     * 执行
     * @return
     */
    public BatchResult<?> execute(){
        return batch.execute();
    }
}

使用redisson批量操作,需要注意一些选项,可参考BatchOptions,一般情况下我们只关心这批命令是否是原子操作、是否关心返回结果、执行时间等。具体的参数选项,可以参考:

批量操作选项类
org.redisson.api.BatchOptions
事务/原子性执行模式
org.redisson.api.BatchOptions.ExecutionMode

使用上面的类测试一下批量操作:

@Test
public void batchTest() throws InterruptedException{
    Batch batch = Batch.of(false, 3000);
    Date date = new Date();
    batch.addToSet("TEST_SET_KEY", 1, new Date(date.getTime() + 10000));
    batch.set("TEST_STRING_KEY", "test");
    BatchResult result = batch.execute();
    System.out.println(JSON.toJSONString(result)); 
    System.out.println(JSON.toJSONString(CacheUtil.getSet("TEST_SET_KEY"))); 
    System.out.println(JSON.toJSONString(CacheUtil.get("TEST_STRING_KEY"))); 
    Thread.sleep(11000);
    System.out.println(JSON.toJSONString(CacheUtil.getSet("TEST_SET_KEY"))); 
    System.out.println(JSON.toJSONString(CacheUtil.get("TEST_STRING_KEY"))); 
}

执行结果如下:

[true,null]
[1]
{"TEST_STRING_KEY":"test"}
[]
{"TEST_STRING_KEY":"test"}

使用redisson的批量执行的确非常简单,也能提高不少性能,这就是redis管道技术的优势。

赞(5)
未经允许不得转载:LoveCTO » springboot项目redis管道(pipeline)批量执行命令,基于redisson

热爱技术 追求卓越 精益求精