StackExchange.Redis 官方文档(六) PipelinesMultiplexers

流水线和复用

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: StackExchange.Redis 是一个.NET平台下的开源Redis客户端库,它提供了一种高性能、稳定和易于使用的方式来与Redis服务器进行通信。它支持异步和同步操作,并提供了一些高级特性,如管道、发布/订阅等。 StackExchange.Redis 具有以下特点: - 快速:通过使用高性能、低级别的Redis通信协议,StackExchange.Redis 可以实现高效的数据访问。 - 可扩展性:StackExchange.Redis 支持分区功能,使它能够在多个Redis节点上分布数据,并且可以在需要时轻松地添加或删除节点。 - 可靠性:StackExchange.Redis 有一个内置的连接池来管理与Redis服务器的连接,从而可以提高性能和可靠性,并避免了频繁的连接/断开开销。 - 易用性:StackExchange.Redis 提供了一个简单的API,使得开发人员能够轻松地与Redis进行交互。 总的来说,如果你在.NET平台上使用RedisStackExchange.Redis 应该是你的首选。 ### 回答2: StackExchange.Redis 是一个基于Redis的 .Net客户端库,由StackExchange团队开发和维护。Redis内存数据库是非常流行的键值对存储,支持复杂数据结构,速度快,有完善的集群方案,在web应用程序、消息系统等应用场景中被广泛使用。 StackExchange.Redis提供了方便易用、高性能、可扩展的API,可以直接向Redis发送命令、订阅和发布消息、连接Redis集群等。他进一步扩展了Redis命令,使其更加简单易用,并支持事务、管道和多线程操作。同时,StackExchange.Redis支持Redis的高级特性,如SortedSet和Hash;而且,它还能够在运行时自动检测Redis服务状态,支持Redis Sentinel、Cluster和多节点环境。 此外,StackExchange.Redis还支持应用程序跟踪(application tracing),采用异步API调用,从而提高了性能和可伸缩性。与其他Redis客户端库不同,StackExchange.Redis实现了连接池、序列化和反序列化器等高级功能,使用起来更加方便和优雅,可以减少代码量和复杂性。 总的来说,StackExchange.Redis是一个很不错的Redis客户端库,它提供了强大而与Redis完全兼容的API,打破了语言壁垒,使得开发者可以在自己喜欢的语言环境(例如.Net)中使用 Redis 。 许多一流的公司如 StackOverflow和GitHub都使用 StackExchange.Redis,证明了它的可靠性和性能优势。 ### 回答3: StackExchange.RedisRedis数据库的一个适用于 .NET 编程语言的客户端。它提供了一组丰富的功能,用于在 .NET 框架内与Redis数据库进行交互。 StackExchange.Redis旨在为 .NET 开发人员提供最佳的Redis集成体验。StackExchange.Redis提供了许多优点,其中最主要的有: 高度优化的读写操作。StackExchange.Redis客户端库具有非常高的效率,用于从Redis服务器读取和写入数据时,可大大减少网络流量和延迟。这使得它成为处理高吞吐量负载的很好的选择。 支持许多复杂数据类型。除了提供基本的字符串和整数类型之外,StackExchange.Redis还支持许多复杂的数据类型,例如哈希表、排序集合和列表数据类型。这些数据类型将极大地帮助开发人员设计和实施高效的Redis应用程序。 易于使用和集成。StackExchange.Redis具有完美的适配性,可以很简单地与 .NET 中的 ASP.NET 应用程序、Windows 服务、控制台应用程序等相集成。此外,它具有丰富的文档、教程和API reference,可以让开发者轻松入手。 另外,StackExchange.Redis还包括许多其他特性,如:连接复用、事务支持、发布与订阅、管道等。这使得它成为在 .NET 编程语言中使用Redis数据库的非常好的选择。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值