服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Redis - redis通过pipeline提升吞吐量的方法

redis通过pipeline提升吞吐量的方法

2019-11-11 14:50zale.tang Redis

下面小编就为大家分享一篇redis通过pipeline提升吞吐量的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

案例目标

简单介绍 redis pipeline 的机制,结合一段实例说明pipeline 在提升吞吐量方面发生的效用。

案例背景

应用系统在数据推送或事件处理过程中,往往出现数据流经过多个网元;

然而在某些服务中,数据操作对redis 是强依赖的,在最近的一次分析中发现:

一次数据推送会对 redis 产生近30次读写操作!

在数据推送业务中的性能压测中,以数据上报 -> 下发应答为一次事务;而对于这样的读写模型,redis 的操作过于频繁,很快便导致系统延时过高,吞吐量低下,无法满足目标;

优化过程 主要针对业务代码做的优化,其中redis 操作经过大量合并,最终降低到原来的1/5,而系统吞吐量也提升明显。

其中,redis pipeline(管道机制) 的应用是一个关键手段。

pipeline的解释

Pipeline指的是管道技术,指的是客户端允许将多个请求依次发给服务器,过程中而不需要等待请求的回复,在最后再一并读取结果即可。

管道技术使用广泛,例如许多POP3协议已经实现支持这个功能,大大加快了从服务器下载新邮件的过程。 Redis很早就支持管道(pipeline)技术。(因此无论你运行的是什么版本,你都可以使用管道(pipelining)操作Redis)

普通请求模型

redis通过pipeline提升吞吐量的方法

[图-pipeline1]

Pipeline请求模型

redis通过pipeline提升吞吐量的方法

[图-pipeline2]

从两个图的对比中可看出,普通的请求模型是同步的,每次请求对应一次IO操作等待;

而Pipeline 化之后所有的请求合并为一次IO,除了时延可以降低之外,还能大幅度提升系统吞吐量。

代码实例

说明

本地开启50个线程,每个线程完成1000个key的写入,对比pipeline开启及不开启两种场景下的性能表现。

相关常量

?
1
2
3
4
5
6
7
8
// 并发任务
private static final int taskCount = 50;
// pipeline大小
private static final int batchSize = 10;
// 每个任务处理命令数
private static final int cmdCount = 1000;
 
private static final boolean usePipeline = true;

初始化连接

?
1
2
3
4
5
6
7
8
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxActive(200);
poolConfig.setMaxIdle(100);
poolConfig.setMaxWait(2000);
poolConfig.setTestOnBorrow(false);
poolConfig.setTestOnReturn(false);
 
jedisPool = new JedisPool(poolConfig, host, port);

并发启动任务,统计执行时间

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) throws InterruptedException {
  init();
 
  flushDB();
 
  long t1 = System.currentTimeMillis();
  ExecutorService executor = Executors.newCachedThreadPool();
 
  CountDownLatch latch = new CountDownLatch(taskCount);
  for (int i = 0; i < taskCount; i++) {
   executor.submit(new DemoTask(i, latch));
  }
 
  latch.await();
  executor.shutdownNow();
 
  long t2 = System.currentTimeMillis();
 
  System.out.println("execution finish time(s):" + (t2 - t1) / 1000.0);
 
 }

DemoTask 封装了执行key写入的细节,区分不同场景

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void run() {
  logger.info("Task[{}] start.", id);
  try {
   if (usePipeline) {
    runWithPipeline();
   } else {
    runWithNonPipeline();
   }
  } finally {
   latch.countDown();
  }
 
  logger.info("Task[{}] end.", id);
 }

不使用Pipeline的场景比较简单,循环执行set操作

?
1
2
3
4
5
6
7
8
9
10
11
12
13
for (int i = 0; i < cmdCount; i++) {
    Jedis jedis = get();
    try {
     jedis.set(key(i), UUID.randomUUID().toString());
    } finally {
     if (jedis != null) {
      jedisPool.returnResource(jedis);
     }
    }
    if (i % batchSize == 0) {
     logger.info("Task[{}] process -- {}", id, i);
    }
   }

使用Pipeline,需要处理分段,如10个作为一批命令执行

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
for (int i = 0; i < cmdCount;) {
    Jedis jedis = get();
 
    try {
     Pipeline pipeline = jedis.pipelined();
     int j;
     for (j = 0; j < batchSize; j++) {
      if (i + j < cmdCount) {
       pipeline.set(key(i + j), UUID.randomUUID().toString());
      } else {
       break;
      }
     }
     pipeline.sync();
     logger.info("Task[{}] pipeline -- {}", id, i + j);
 
     i += j;
 
    } finally {
     if (jedis != null) {
      jedisPool.returnResource(jedis);
     }
    }
 
   }

运行结果

不使用Pipeline,整体执行26s;而使用Pipeline优化后的代码,执行时间仅需要3s!

NoPipeline-stat

redis通过pipeline提升吞吐量的方法

[图-nopipeline]

Pipeline-stat

redis通过pipeline提升吞吐量的方法

[图-pipeline]

注意事项

pipeline机制可以优化吞吐量,但无法提供原子性/事务保障,而这个可以通过Redis-Multi等命令实现。

参考这里

部分读写操作存在相关依赖,无法使用pipeline实现,可利用Script机制,但需要在可维护性方面做好取舍。

扩展阅读

官方文档-Redis-Pipelining

官方文档-Redis-Transaction

以上这篇redis通过pipeline提升吞吐量的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。

延伸 · 阅读

精彩推荐
  • Redis如何使用Redis锁处理并发问题详解

    如何使用Redis锁处理并发问题详解

    这篇文章主要给大家介绍了关于如何使用Redis锁处理并发问题的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Redis具有一定的参考学习...

    haofly4522019-11-26
  • RedisRedis集群的5种使用方式,各自优缺点分析

    Redis集群的5种使用方式,各自优缺点分析

    Redis 多副本,采用主从(replication)部署结构,相较于单副本而言最大的特点就是主从实例间数据实时同步,并且提供数据持久化和备份策略。...

    优知学院4082021-08-10
  • Redis《面试八股文》之 Redis十六卷

    《面试八股文》之 Redis十六卷

    redis 作为我们最常用的内存数据库,很多地方你都能够发现它的身影,比如说登录信息的存储,分布式锁的使用,其经常被我们当做缓存去使用。...

    moon聊技术8182021-07-26
  • RedisRedis 6.X Cluster 集群搭建

    Redis 6.X Cluster 集群搭建

    码哥带大家完成在 CentOS 7 中安装 Redis 6.x 教程。在学习 Redis Cluster 集群之前,我们需要先搭建一套集群环境。机器有限,实现目标是一台机器上搭建 6 个节...

    码哥字节15752021-04-07
  • RedisRedis Template实现分布式锁的实例代码

    Redis Template实现分布式锁的实例代码

    这篇文章主要介绍了Redis Template实现分布式锁,需要的朋友可以参考下 ...

    晴天小哥哥2592019-11-18
  • Redis关于Redis数据库入门详细介绍

    关于Redis数据库入门详细介绍

    大家好,本篇文章主要讲的是关于Redis数据库入门详细介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览...

    沃尔码6982022-01-24
  • Redisredis缓存存储Session原理机制

    redis缓存存储Session原理机制

    这篇文章主要为大家介绍了redis缓存存储Session原理机制详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    程序媛张小妍9252021-11-25
  • Redis详解三分钟快速搭建分布式高可用的Redis集群

    详解三分钟快速搭建分布式高可用的Redis集群

    这篇文章主要介绍了详解三分钟快速搭建分布式高可用的Redis集群,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    万猫学社4502021-07-25