最近开始又接触到了Redis,之前在工作中使用Redis的时候,由于QPS不高,都是直接get/set搞定了。这次遇到的业务数据量比较大,更新也很频繁,Redis使用是集群模式,所以本文记录下捣鼓出来的如何在集群模式下使用pipeline进行批量操作的代码。为啥要捣鼓...因为网上找到的方法都不太靠谱
Redis集群是没法执行一些批量操作命令的,如mget,pipeline等。这是因为redis将集群划分为16384个slot,不同的key会划分到不同的slot,集群中的每个节点对应一批slot。jedis客户端并没有封装批量操作的命令。
但是在Redis集群中,每个redis节点都能单独对外提供服务。同时Jedis客户端提供了计算key的slot方法,已经slot和节点之间的映射关系,通过这两个数据,就可以计算出每个key所在的节点,然后对相同节点上的数据使用pipeline获取数据。
本人使用的redis版本是7.x,jedis客户端版本是4.3.1
如何判断key所属的节点:
首先判断key所属的slot,使用JedisClusterCRC16.getslot()方法,可以直接计算出key所属的slot。
接着就是计算slot属于哪个node了。这里的jedisCluster是创建好的集群连接,可以获取slot对应的Connection,这个Connection就是Redis单节点的连接。Connection内部会有一个变量叫privat ConnectionPool memberOf 变量记录这个连接属于哪个连接池(这里的连接池就是类似创建单节点的JedisPool)。用反射的方式去获取每个slot对应的ConnectionPool变量:
同时jedisCluster还提供了getClusterNodes()方法,对应的返回结果是Map<String,ConnectionPool> key是节点信息,value为单个节点的连接池信息。
这样,通过ConnectionPool引用的对比,就可以获取到 key -> slot -> node 这样的一串映射关系,从而也就知道了key 和 node之间的对应关系!
Redis集群执行pipeline:
知道了 key -> slot -> node 三者之间的对应关系之后,接下来的事情就很好办了。讲属于同一个node的key放到同一个List里面。然后通过jedisCluster.getClusterNodes().get(***node编号***).getResurce()方法获取单个redis节点连接池中的单个redis连接。用jedis类封装一下,就可以愉快的进行查询啦: