介绍Redis客户端Redisson的批处理命令

背景

最近在做服务优化,优化的核心是利用Redis作为实时数据的存储中间件,降低MySQL的压力。大量的Redis操作充斥在单个方法里,而且是循环处理,每次循环的量预估有10万次,如果是这样操作Redis的话,Redis的QPS会很高,容易造成Redis服务的不稳定。

解决方案

Redis有管道(Pipelining)命令可以减少RTT,查阅redisson的文档可以发现RBatch这个命令,对应实现Redis的管道  10. 额外功能 · redisson/redisson Wiki · GitHub

 代码

用户可以通过以下方式调整通过管道方式发送命令的方式:

BatchOptions options = BatchOptions.defaults()
// 指定执行模式
//
// ExecutionMode.REDIS_READ_ATOMIC - 所有命令缓存在Redis节点中,以原子性事务的方式执行。
//
// ExecutionMode.REDIS_WRITE_ATOMIC - 所有命令缓存在Redis节点中,以原子性事务的方式执行。
//
// ExecutionMode.IN_MEMORY - 所有命令缓存在Redisson本机内存中统一发送,但逐一执行(非事务)。默认模式。
//
// ExecutionMode.IN_MEMORY_ATOMIC - 所有命令缓存在Redisson本机内存中统一发送,并以原子性事务的方式执行。
//
.executionMode(ExecutionMode.IN_MEMORY)

// 告知Redis不用返回结果(可以减少网络用量)
.skipResult()

// 将写入操作同步到从节点
// 同步到2个从节点,等待时间为1秒钟
.syncSlaves(2, 1, TimeUnit.SECONDS)

// 处理结果超时为2秒钟
.responseTimeout(2, TimeUnit.SECONDS)

// 命令重试等待间隔时间为2秒钟
.retryInterval(2, TimeUnit.SECONDS);

// 命令重试次数。仅适用于未发送成功的命令
.retryAttempts(4);

使用方式如下:

RBatch batch = redisson.createBatch();
batch.getMap("test").fastPutAsync("1", "2");
batch.getMap("test").fastPutAsync("2", "3");
batch.getMap("test").putAsync("2", "5");
batch.getAtomicLongAsync("counter").incrementAndGetAsync();
batch.getAtomicLongAsync("counter").incrementAndGetAsync();

BatchResult res = batch.execute();
// 或者
Future asyncRes = batch.executeAsync();
List response = res.getResponses();
res.getSyncedSlaves();

以上是官方给出的案例,下面结合项目实际给出示例。

public int getRoomActiveCountBatch(List roomIds) {
        int totalRoomNum = 0;
        RBatch rBatch = redissonClient.createBatch();
        for (String roomId : roomIds) {
            rBatch.getScoredSortedSet(RedisKeyConstants, StringCodec.INSTANCE).getScoreAsync(roomId);
        }
        BatchResult res = rBatch.execute();
        List list = res.getResponses();
        if (CollectionUtils.isNotEmpty(list)) {
            totalRoomNum = list.stream().mapToInt(Double::intValue).sum();
        }
        return totalRoomNum;
    }
 public List enumRoomsBatchAsync() {
        List rtRoomList = new ArrayList<>();
        RLexSortedSet allSortSet = redissonClient.getLexSortedSet(RedisKeyConstants.Room_Real_Account_KEY_Registry);
        Collection roomIds = allSortSet.readAll();
        RBatch rBatch = redissonClient.createBatch();
        for (String roomId : roomIds) {
            rBatch.getMap(RedisKeyConstants, StringCodec.INSTANCE).readAllMapAsync();
        }
        BatchResult res = rBatch.execute();
        List> list = res.getResponses();
        for (Map map : list) {
            RTRoom rtRoom = new RTRoom();
            rtRoom.FromHashMapEntry(map);
            rtRoomList.add(rtRoom);
        }
        return rtRoomList;
    }

你可能感兴趣的:(redis,数据库,nosql)