criticalSection(消息之间的独立性,保证状态的一致性)
2017-08-14 11:21
246 查看
criticalSection的解析:
调用queue获得临界区,维持单一代码运行 ,防伪并发
同一个 skynet 服务中的一条消息处理中,如果调用了一个阻塞 API ,那么它会被挂起。挂起过程中,这个服务可以响应其它消息。这很可能造成时序问题,要非常小心处理。
一旦你的消息处理过程有外部请求,那么先到的消息未必比后到的消息先处理完。且每个阻
塞调用之后,服务的内部状态都未必和调用前的一致(因为别的消息处理过程可能改变状态)。
skynet.queue 模块可以帮助你回避这些伪并发引起的复杂性。
local queue = require “skynet.queue”
获得的 queue 是一个函数,每次调用它都可以得到一个新的临界区。临界区可以保护一段代码不被同时运行。
local cs = queue() -- cs 是一个执行队列 local CMD = {} function CMD.foobar() cs(func1) -- push func1 into critical section end function CMD.foo() cs(func2) -- push func2 into critical section end
比如你实现了这样一个消息分发器,支持 foobar 和 foo 两类消息。如果你使用 cs 这个 skynet.queue 创建出来的队列。那么在上面的处理流程中, func1 和 func2 这两个函数,都不会在执行过程中相互被打断。
如果你的服务收到多条 foobar 或 foo 消息,一定是处理完一条后,才处理下一条,即使 func1 或 func2 中有 skynet.call 这类的阻塞调用。一旦它们被挂起,新的消息到来后,新的处理流程会被排到 cs 队列尾,等待前面的流程执行完毕才会开始。
注:在 func1 函数内部再调用 cs 是合法的。即:
local function func2() -- step 3 end local function func1() -- step 2 cs(func2) -- step 4 end function CMD.foobar() -- step 1 cs(func1) -- push func1 into critical section -- step 5 end
如果你这样写,每次收到 foobar 消息后,程序流程会按 step 1, step 2, step 3, step 4, step 5 这样执行,而不会死锁。
在这个过程中,如果 foobar 消息的处理流程被挂起,即使新的 foobar 消息到来,那么,新的消息会立刻执行 step 1 (因为没有被 cs 保护),然后等前一次的 step 4 结束后(step 5 不在 cs 保护中),开始新的 step 2 。
相关文章推荐
- STORM-消息一致性保证
- 【分布式】--消息kafka保证消顺序一致性(358)
- 消息中间件保证消息一致性解决方案
- 保证MQ消息传递的一致性
- 分布式事务:不过是在一致性、吞吐量和复杂度之间,做一个选择 分布式系统 消息系统
- sql:如何恢复数据库到两个备份时间点之间的状态
- 线程的基本概念,状态,和状态之间的关系
- 分布式与集群的区别,一致性hash,hadoop与HBASE,消息,关于分布式系统的数据一致性问题(来自公众号:360doc个人图书馆)
- 世纪佳缘信息爬取存储到mysql,下载图片到本地,从数据库选取账号对其发送消息更新发信状态
- zookeeper 永久监听节点 来保证集群间一致性
- Twitter Storm如何保证消息不丢失
- SIP应答消息状态码与功能
- Handler具体解释系列(四)——利用Handler在主线程与子线程之间互发消息
- HTTP 状态消息大全
- (4.1.21)Android 主线程和线程之间相互发送消息
- 消息“时序”与“一致性”为何这么难
- 用消息队列和消息应用状态表来消除分布式事务
- 主用Server和备用Server的数据如何同步和保证一致性?
- python实现简单socket程序在两台电脑之间传输消息的方法
- android openfire 表中各状态之间数值标记