网站开发用什么编程,抖音代运营费用一年多少钱,wordpress精简版,长沙网站定制文章目录 【README】【1】redis流水线Pipeline【1.1】redis流水线概念【1.2】redis流水线性能测试【1.2.1】使用流水线与未使用流水线的性能对比【1.2.2】使用流水线与redis原生批量命令的性能对比【1.2.3】流水线缺点 【1.3】Jedis客户端执行流水线【1.3.1】Jedis客户端执行流… 文章目录 【README】【1】redis流水线Pipeline【1.1】redis流水线概念【1.2】redis流水线性能测试【1.2.1】使用流水线与未使用流水线的性能对比【1.2.2】使用流水线与redis原生批量命令的性能对比【1.2.3】流水线缺点 【1.3】Jedis客户端执行流水线【1.3.1】Jedis客户端执行流水线实现批量删除代码实践【1.3.2】Jedis客户端执行流水线并获取执行结果代码实践 【README】
本文总结自《redis开发与运维》作者付磊张益军墙裂推荐
本文使用的redis版本是 7.0.15 ;本文主要介绍redis流水线概念及jedis操作流水线代码实践代码参见 https://github.com/TomJourney/redisDiscover/tree/master 【1】redis流水线Pipeline
1redis客户端执行一条命令分为4个步骤
发送命令命令排队命令执行返回结果
2RTT往返时间发送命令与返回结果的执行耗时RTT-Round Trip Time
3问题与解决方法 问题redis的批量操作命令能够有效节约RTT如mgetmset。但问题是大部分命令不支持批量操作如hgetall即批量业务场景只能执行单条命令网络IO高导致RTT高。 【例】 redis客户端在北京服务器在上海两地直线距离为1300公里1次RTT时间1300*2/(300000 * 2/3) 13ms光在真空中的速度为每秒30w公里假设光纤传播速度为光速的2/3即每秒20w公里若批量业务场景需要执行10次hgetall则需要130ms单单操作redis的网络io就有130ms还不算正常的业务逻辑耗时显然操作redis的耗时是不合理的补充 一般一次请求响应的网络耗时不超过200ms 解决方法使用redis流水线技术
4其他补充 redis命令真正执行的耗时是微秒级别1s1000000 microsecond所以才会有redis性能瓶颈在网络开销的说法 【1.1】redis流水线概念
1redis流水线能够将一组redis命令进行组装 通过一次RTT传输给redis再将这组执行结果一次性返回给客户端即使用pipeline执行n次命令耗时1个RTT 【1.2】redis流水线性能测试
【1.2.1】使用流水线与未使用流水线的性能对比
1在不同网络环境下 10000条set未使用流水线命令 与 使用流水线命令执行耗时如下。 2redis流水线性能对比结论
流水线执行速度一般比逐条执行要快客户端与服务器的网络延时越大则流水线的效果越明显 【1.2.2】使用流水线与redis原生批量命令的性能对比
1流水线与原生批量命令区别
流水线执行命令不是原子的而原生批量命令是原子的流水线支持多个命令而原生批量命令是一个命令操作多个key如mset流水线需要客户端与服务器同时提供支持而原生批量命令是redis服务器提供支持 【1.2.3】流水线缺点
1每次流水线封装的命令不能太多流水线组装的命令过多可能导致阻塞
一方面一次流水线可能增加客户端的等待时间另一方面造成一定的网络阻塞
2解决方法 可以将包含大量命令的流水线拆分为多个小流水线 【1.3】Jedis客户端执行流水线
【1.3.1】Jedis客户端执行流水线实现批量删除代码实践
【PooledJedisBatchDelViaPipeline】池化jedis操作流水线
public class PooledJedisBatchDelViaPipeline {public static void main(String[] args) {BusiJedisFactoryUsingPool busiJedisFactoryUsingPool BusiJedisFactoryUsingPool.build();// 从jedis连接池获取jedis对象Jedis jedis busiJedisFactoryUsingPool.getJedis();try {System.out.println(jedis.get(user01));System.out.println(jedis.get(user02));batchDelete(jedis, Arrays.asList(user01, user02));} catch (Exception e) {throw new IllegalStateException(e.getMessage(), e);} finally {if (Objects.nonNull(jedis)) {jedis.close();}}// 删除键之后获取键// 从jedis连接池获取jedis对象System.out.println( 删除键之后获取键 );jedis busiJedisFactoryUsingPool.getJedis();try {System.out.println(jedis.get(user01));System.out.println(jedis.get(user02));} catch (Exception e) {throw new IllegalStateException(e.getMessage(), e);} finally {if (Objects.nonNull(jedis)) {jedis.close();}}}private static void batchDelete(Jedis jedis, ListString keys) {// 生成pipeline对象Pipeline pipeline jedis.pipelined();for (String key : keys) {pipeline.del(key);}// 提交命令到redispipeline.sync();}
}【日志】
zhagnsan01
zhagnsan02删除键之后获取键
null
null【代码解说】
jedis.pipelined() 创建流水线对象pipeline.del(String key) 与 jedis.del(String key) 的写法是一致的只不过pipeline.del(String key) 不会立即执行命令pipeline.sync() 执行流水线组装的多个命令发送组装多个命令的流水线到redis服务器 【1.3.2】Jedis客户端执行流水线并获取执行结果代码实践
1syncAndReturnAll() 执行流水线命令并获取执行结果
【PooledJedisSetAndGetResultViaPipeline】
public class PooledJedisSetAndGetResultViaPipeline {public static void main(String[] args) {BusiJedisFactoryUsingPool busiJedisFactoryUsingPool BusiJedisFactoryUsingPool.build();// 从jedis连接池获取jedis对象Jedis jedis busiJedisFactoryUsingPool.getJedis();try {setAndGetReulst(jedis);} catch (Exception e) {throw new IllegalStateException(e.getMessage(), e);} finally {if (Objects.nonNull(jedis)) {jedis.close();}}}private static void setAndGetReulst(Jedis jedis) {// 生成pipeline对象Pipeline pipeline jedis.pipelined();pipeline.set(user03, zhangsan03);pipeline.incr(age);// syncAndReturnAll 执行流水线命令并返回结果ListObject resultList pipeline.syncAndReturnAll();for (Object result : resultList) {System.out.println(result);}}
}
【日志】
OK
2