问题描述
我想最好的办法就是发布和订阅使用BookSleeve渠道是什么。目前,我实现了一些静态方法(见下文),让我发布的内容要与新创建的通道特定的频道存储在私有静态字典<字符串,RedisSubscriberConnection> subscribedChannels;
。
这给我想要发布到渠道和相同的应用程序内订阅频道(:我的包装是一个静态类注)是正确的做法。它是足以创造一个通道,即使我想发布和订阅?很显然,我不会发布到比我会在同一应用程序内订阅同一通道。但是我测试了它和它的工作:
RedisClient.SubscribeToChannel(测试)等待();
RedisClient.Publish(测试,测试信息);
和它的工作。
下面我的问题:
1)会不会是更有效地设置一个专用的发布渠道和专用订阅渠道,而不是使用一个通道为?
2)什么是道和PatternSubscription语义上的区别?我的理解是,我可以订阅几个主题,通过 PatternSubscription()
在同一个信道上,是否正确?但是,如果我想有调用为每一个主题不同的回调我就必须设置为每个主题正确的渠道?是有效的,或者你会建议不要呢?
下面的代码片段。
谢谢!
公共静态任务<长>发布(串通道,字节[]消息)
{
返回connection.Publish(通道,消息);
}
公共静态任务SubscribeToChannel(字符串CHANNELNAME)
{
串subscriptionString = ChannelSubscriptionString(CHANNELNAME);
RedisSubscriberConnection通道= connection.GetOpenSubscriberChannel();
subscribedChannels [subscriptionString] =通道;
返回channel.PatternSubscribe(subscriptionString,OnSubscribedChannelMessage);
}
公共静态任务UnsubscribeFromChannel(字符串CHANNELNAME)
{
串subscriptionString = ChannelSubscriptionString(CHANNELNAME);
如果(subscribedChannels.Keys.Contains(subscriptionString))
{
RedisSubscriberConnection通道= subscribedChannels [subscriptionString]
任务task = channel.PatternUnsubscribe(subscriptionString);
//删除频道订阅
channel.Close(真);
subscribedChannels.Remove(subscriptionString);
返回任务;
}
,否则
{
返回NULL;
}
}
私人静态字符串ChannelSubscriptionString(字符串CHANNELNAME)
{
返回CHANNELNAME +*;
}
1:只有一个在你的榜样通道(测试
);一个通道仅仅是用于特定的发布/订阅交换的名称。它是,然而,需要使用2的连接的由于如何redis的API的工作的细节。有一个连接的任何订阅不能做任何事情,除了:
- 收听消息
- 管理自己的订阅(
订阅
,psubscribe
,取消
,punsubscribe
)
不过,我不明白这样的:
私有静态字典<字符串,RedisSubscriberConnection>
除非你是迎合特定于你的东西你不应该需要一个以上的用户连接。单个用户连接可以处理订阅任意数量。 客户名单
上的快速检查在我的服务器之一,我(在写作的时间)23002订阅一个连接。 。这也许可以减少,但:它的工作原理
2:模式订阅支持通配符;所以,而非订阅 /主题/ 1
, /主题/ 2 /
等等,你可以订阅 /主题/ *
。在按用于发布实际
的渠道提供给接收器回调签名的一部分的名称。
这两者都可以正常工作。应该注意的是,的业绩发布
是由独特的订阅总数的影响 - 但坦率地它仍然是愚蠢快(如:0毫秒),即使你有数十多数千采用订阅的频道的订阅
,而不是 psubscribe
。
不过从
I recommend reading the redis documentation of pub/sub.
Edit for follow on questions:
that won't make any difference at all; since you mention Result
/ Wait()
, I assume you're talking about BookSleeve - in which case the multiplexer already preserves command order. Redis itself is single threaded, and will always process commands on a single connection in order. However: the callbacks on the subscriber may be executed asynchronously and may be handed (separately) to a worker thread. I am currently investigating whether I can force this to be in-order from RedisSubscriberConnection
.
Update: from 1.3.22 onwards you can set the CompletionMode
to PreserveOrder
- then all callbacks will be completed sequentially rather than concurrently.
Firstly, that time sounds high - testing locally I get (for 100,000 publications, including waiting for the response for all of them) 1766ms (local) or 1219ms (remote) (that might sound counter-intuitive, but my "local" isn't running the same version of redis; my "remote" is 2.6.12 on Centos; my "local" is2.6.8-pre2 on Windows).
I can't make your actual server faster or speed up the network, but: in case this is packet fragmentation, I have added (just for you) a SuspendFlush()
/ ResumeFlush()
pair. This disables eager-flushing (i.e. when the send-queue is empty; other types of flushing still happen); you might find this helps:
conn.SuspendFlush();
try {
// start lots of operations...
} finally {
conn.ResumeFlush();
}
Note that you shouldn't Wait
until you have resumed, because until you call ResumeFlush()
there could be some operations still in the send-buffer. With that all in place, I get (for 100,000 operations):
local: 1766ms (eager-flush) vs 1554ms (suspend-flush)
remote: 1219ms (eager-flush) vs 796ms (suspend-flush)
As you can see, it helps more with remote servers, as it will be putting fewer packets through the network.
I think that is addressed by the above - but note that recently CreateBatch
was added too. A batch operates a lot like a transaction - just: without the transaction. Again, it is another mechanism to reduce packet fragmentation. In your particular case, I suspect the suspend/resume (on flush) is your best bet.
As long as you're not performing blocking operations (blpop
, brpop
, brpoplpush
etc), or putting oversized BLOBs down the wire (potentially delaying other operations while it clears), then a single connection of each type usually works pretty well. But YMMV depending on your exact usage requirements.
这篇关于如何在BookSleeve / Redis的PubSub的工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!