redis pipeline-批量操作的性能优化方案

pipeline

该部分内容大都引用自《Redis开发与运维》付磊,张益军

Redis客户端执行一条命令分为如下四个过程:
1)发送命令
2)命令排队
3)命令执行
4)返回结果
第1步和第4步称为Round Trip Time(RTT,往返时间)。

距离越远网络耗时越长
Redis服务端在上海,两地直线距离约为1300公里,那么1次RTT时间=1300×2/(300000×2/3)=13毫秒(光在真空中传输速度为每秒30万公里,这里假设光纤为光速的2/3),那么客户端在1秒内大约只能执行80次左右的命令,这个和Redis的高并发高吞吐特性背道而驰。
结论:同机房和同机器会比较快,跨机房跨地区会比较慢。

pipeline与非pipeline的命令模式图示:
在这里插入图片描述

在这里插入图片描述
《Redis开发与运维》性能压测
仅能作为参考,说明pipeline对性能的提升
在这里插入图片描述
pipeline与原生批量命令的区别
可以使用Pipeline模拟出批量操作的效果,但是在使用时要注意它与原生批量命令的区别,具体包含以下几点:
·原生批量命令是原子的,Pipeline是非原子的。
·原生批量命令是一个命令对应多个key,Pipeline支持多个命令。
·原生批量命令是Redis服务端支持实现的,而Pipeline需要服务端和客户端的共同实现。

最佳实践
Pipeline虽然好用,但是每次Pipeline组装的命令个数不能没有节制,否则一次组装Pipeline数据量过大,一方面会增加客户端的等待时间,另一方面会造成一定的网络阻塞,可以将一次包含大量命令的Pipeline拆分成多次较小的Pipeline来完成。Pipeline只能操作一个Redis实例,但是即使在分布式Redis场景中,也可以作为批量操作的重要优化手段。

Jedis中Pipeline的使用

sync()没有返回值
syncAndReturnAll存在返回值

package redis;

import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

import java.util.List;

public class UseJedisPipeline {

    @Test
    public void pipelineUsageWithoutResult() {
        Jedis jedis = null;
        try {
            jedis = new Jedis("192.168.42.111", 6379);
            if (!"PONG".equals(jedis.ping())) {
                throw new RuntimeException("连接失败");
            }
            Pipeline pipeline = jedis.pipelined();
            for (int i = 0; i < 100; i++){
                pipeline.set("n" + i, String.valueOf(i));
            }
            pipeline.sync();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }


    @Test
    public void pipelineUsageWithResult() {
        Jedis jedis = null;
        try {
            jedis = new Jedis("192.168.42.111", 6379);
            if (!"PONG".equals(jedis.ping())) {
                throw new RuntimeException("连接失败");
            }
            Pipeline pipeline = jedis.pipelined();
            for (int i = 0; i < 100; i++){
                pipeline.set("n" + i, String.valueOf(i));
            }
            for (int i = 0; i < 100; i++){
                pipeline.get("n" + i);
            }
            List<Object>  results = pipeline.syncAndReturnAll();
            for(Object result:results){
                System.out.println(result);
            }
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值