流水线和复用

糟糕的时间浪费。现代的计算机以惊人的速度产生大量的数据,而且高速网络通道(通常在重要的服务器之间同时存在多个链路)提供了很高的带宽,但是计算机花费了大量的时间在 等待数据 上面,这也是造成使用持久性链接的编程方式越来越流行的原因之一。常规的编码方式:

string a = db.StringGet("a");
string b = db.StringGet("b");

就步骤而言,它看起来像下面这样:

[req1]                         # client: the client library constructs request 1[c=>s]                    # network: request one is sent to the server[server]             # server: the server processes request 1[s=>c]        # network: response one is sent back to the client[resp1]  # client: the client library parses response 1[req2][c=>s][server][s=>c][resp2]

高亮 client 端正在做的事情:

[req1][====waiting=====][resp1][req2][====waiting=====][resp2]

如果按照时间缩放的话,就会看到大部分的时间都耗在了 等待 上面。

Pipelining

由于上述的原因,很多 redis 客户端允许使用 pipelining; 这是一种可以一次性通过管道发送多条消息的方式而不用一条一条的发送等.待,而且可以在等到回复时一并处理他们. .NET 的异步方法。

举例来说

var aPending = db.StringGetAsync("a");
var bPending = db.StringGetAsync("b");
var a = db.Wait(aPending);
var b = db.Wait(bPending);

在这里使用 db.Wait 可以自动采用配置的超时时间, 但也可以使用 aPending.Wait() 或者 Task.WaitAll(aPending, bPending);的方式,根据你自己的喜好来. 这样一来 20 个请求可能合并为一个请求。

Fire and Forget

pipelining 的一种特殊场景是,我们并不关心某个操作的返回结果,这样的话我们的代码可以马上接着往下执行,而那个放入到队列中的操作将会在后台执行. 通常来说,这意味我们可以把并行的操作放到一个单独的 caller 的连接上执行. 这种情况下, 我们可以使用 flags 参数达到这样的目的.

// sliding expiration
db.KeyExpire(key, TimeSpan.FromMinutes(5), flags: CommandFlags.FireAndForget);
var value = (string)db.StringGet(key);

FireAndForget 标志使得client library 正常的把要做的事情的排成队列, 但是会马上返回一个默认的值,这个默认值没有任何的实用意义. 这也适用于 *Async 方法:会返回一个已经完成的 Task<T>.

Multiplexing 多路复用

pipelining 已经很好了,但是很多情况下一个代码块只需要一个单独的值 (或许这个代码块希望执行一些简单的操作,但是这些操作是相互依赖的). 这也就是说我们仍然会消耗大量的时间在client和server之间交互等待. 假如有一个业务繁忙的应用, 或许是一个网站服务器. 这些应用往往都是并发的, 所以如果有20个并行的应用请求数据,你可能采用建立20个链接的方式,或者异步使用同一个链接(最后一个请求需要等之前19个完成). 或者做个让步, 使用一个拥有5个链接的程序池 - 但是不管你怎么做,都会有大量的等待发生。StackExchange.Redis 没有做以上的事情 它只是尽可能的充分复用一个链接. 当被不同的调用者同时调用时,它会 自动地将不同的请求放到队列中, 所以无论请求使用同步或者异步的方式,要做的事情都会放到队列中. 所以我们可能有10个或者20个 "get a and b" 的场景,他们都会尽快的获取链接执行命令.

鉴于以上的原因,StackExchange.Redis 没有( 将来也不会 )提供 "blocking pops" (BLPOP, BRPOP and BRPOPLPUSH). 因为这会使得一个单独的调用者减慢整个的多路复用环境,堵塞其他所有的调用者. 唯一的例外 StackExchange.Redis 需要验证事务的先决条件时需要保证工作的时间. 这也是StackExchange.Redis 将这些条件包装在 Condition 的实例中. Read more about transactions here, 如果真的想用 "blocking pops", 这里墙裂建议你使用pub/sub的方式替代.

sub.Subscribe(channel, delegate {string work = db.ListRightPop(key);if (work != null) Process(work);
});
//...
db.ListLeftPush(key, newWork, flags: CommandFlags.FireAndForget);
sub.Publish(channel, "");

这实现了相同的目的,而不需要阻塞操作:

  • data 没有通过 pub/sub 的方式发送; pub/sub 只是用来通知worker去检查队列是否有数据
  • 如果没有worker,新的item 会存在list里面; 这项工作也不算是完全失败
  • 一个worker 只能 pop 一个值; 就算有很多的 consumer 消费这个队列,其中的一些 consumer 被通知到也拿不到值去做接下来的事情
  • 当你重启一个worker时,你应该假定队列中有 work 这样可以消费积压的work
  • 但除此之外,语义与 blocking pops相同

StackExchange.Redis的复用特性使得使用普通的简单代码时,在一个连接上达到极高的吞吐量成为可能。.

Concurrency

pipeline / multiplexer / future-value 只会在 continuation-based 的异步代码上起到较好的作用

string value = await db.StringGetAsync(key);
if (value == null) {value = await ComputeValueFromDatabase(...);db.StringSet(key, value, flags: CommandFlags.FireAndForget);
}
return value;

转发请标注本文链接地址:(https://www.cnblogs.com/ArvinZhao/p/6825870.html)

转载于:https://www.cnblogs.com/ArvinZhao/p/6825870.html

StackExchange.Redis 官方文档(六) PipelinesMultiplexers相关推荐

  1. StackExchange.Redis 官方文档(五) Keys, Values and Channels

    StackExchange.Redis 官方文档(五) Keys, Values and Channels 原文:StackExchange.Redis 官方文档(五) Keys, Values an ...

  2. StackExchange.Redis官方文档(四)【键、值以及通道】

    键.值以及通道 在对待Redis时候,键和其他的事物之间有个相当重要的区别.键是在数据库中一段数据的唯一标识(可能String,List,Hash或者其他的Redis数据类型).键是没有任何实质意义, ...

  3. StackExchange.Redis 官方文档(二) Configuration

    配置 有多种方式可以配置redis,StackExchange.Redis提供了一个丰富的配置模型,在执行Connect (or ConnectAsync) 时被调用: var conn = Conn ...

  4. StackExchange.Redis官方文档(一)【基本用法】

    基本用法 ConnectionMultiplexer 类是StackExchange.Redis的中枢对象,它在StackExchange.Redis名称空间中: 这个对象封装了很多基础服务对象的详细 ...

  5. 《Redis官方文档》用Redis构建分布式锁

    <Redis官方文档>用Redis构建分布式锁 用Redis构建分布式锁 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现 ...

  6. Redis官方文档(入门必备)

    函数大全 中文文档 官方文档

  7. 《Redis官方文档》Redis调试指南

    原文链接      译者:Adeline Redis开发过程中十分注重其稳定性:我们尽一切努力来保证每一个版本的稳定,不出现突然崩溃等情况.但是即使在我们百分百的努力下,仍然没办法保证百分百的无bug ...

  8. Redis 官方文档阅读之 High Availability

    文章目录 Distributed nature of Sentinel(sentinel的分布式特性) Quick Start Obtaining Sentinel(获取哨兵) Running Sen ...

  9. redis官方文档中文版_Partitioning : 怎么样将你的数据分布在多个redis instance上?

    本文转载自[url]http://skynetdoc.com/?p=119[/url] 本人顺便修正了一些文字上的复制粘贴小错误,以及更新了一些文字以和英文版保持一致. Partitioning 能够 ...

最新文章

  1. 未来社会是什么样子的?您猜对了吗?
  2. 尝鲜 workerize 源码
  3. 积分和人民币比率_通过比率路由到旧版和现代应用程序–通过Spring Cloud的Netflix Zuul...
  4. java栈API_Java中的堆栈API——Stack
  5. 牛客网SQL篇刷题篇(1-2)
  6. LeetCode 413. Arithmetic Slices
  7. leetcode142. 环形链表 II
  8. mysql 在结果集中随机_MySql从表结果集中随机取一条数据
  9. Android 自定义万能的抽屉布局(侧滑菜单)GenericDrawerLayout
  10. 看这里NetWork location failed because baidu location service can not decrypt the request query,so加载不到
  11. CISP 和 NISP差别一览
  12. 双机互联攻略之超强、完全篇!
  13. An error occurred while starting the application
  14. 这个彩蛋表明,图灵测试评估的也许不是计算机,而是人类……
  15. 三点法求三维坐标精度误差评估实验
  16. vue+element树形控件实现根据条件(例id)禁用选项
  17. 2.5 C语言入职例程二:指针
  18. 修复 Ghost win10系统不能启动问题
  19. 获取手机屏幕大小、密度、分辨率、状态栏、标题栏高度
  20. 前端多级组织(部门)结构展示

热门文章

  1. 【NC14 按之字形顺序打印二叉树】
  2. 【LightOJ - 1030】Discovering Gold(概率dp,数学期望,期望的线性性)
  3. 【2019牛客暑期多校训练营(第一场) - H】XOR(线性基,期望的线性性)
  4. 【ZOJ - 4033】CONTINUE...? (思维,整体思想,分组思想)
  5. 【 CodeForces - 799A 】Carrot Cakes(模拟,细节,有坑)
  6. 【51Nod - 1215 】数组的宽度 (单调栈 或 分治 或 单调队列,算贡献,需去重)
  7. 从零开始学视觉Transformer(4):ViT模型全流程解析
  8. mysql etl工具有哪些_常见ETL工具一览,你知多少?
  9. java button 圆角_UIButton具有渐变边框和圆角
  10. 最长上升子序列 java_最长上升子序列 O(nlogn)解法 (java)