由于工作上关系目前经常被各种并发数据问题搞得焦头烂额, 要么要性能舍弃数据上得一致性, 要么要一致性但是却得到了特别糟糕的响应. 难道鱼和熊掌真的无法兼得吗?
然后找到了类似奥尔良这种基于 Actor 模型的 kuangjia
首先本人因为是 C# 系的所以暂不考虑 Java 系那套, 那摆在面前的此类型的框架其实就 2 个. Akka.NET 和 Orleans.
什么是 Actor?
Actor 应该说是一种编程模型, 一个 Actor 是一个最基本的计算单原, 他能接收消息并执行计算(一个行为)
它最重要的特性是每个 Actor 之间互相隔离, 互补共享内存, 也就是说每个 Actor 都能维持一个私有状态且不能被别人所改变.
这对于我们意味着什么呢? 想下一般我们遇到的并发问题, 是不是在我们执行某个操作的时候, 一个数据不正确的被另一个操作所干扰, 导致数据最终混乱, 而 Actor 则确保自己的数据不能被别人改变 (独立维护自己的状态) 以便使得最终一致.
wait
如果 Actor 自己数据不能被别人改变, 那就是顺序执行? 那会不会很慢?
对于一个 Actor 来说, 没错, 他还真的就顺序执行, 因此能确保准确性
但是你真正系统里肯定不会只有一个 Actor, 而是由很多 Actor 组成, 每个 Actor 之间是能并行的(因为他们不共享数据, 所以他们可以互相独立的正确处理)
具体来说, 当并行的消息到达一个 Actor 的时候, 它会存储到一个 MailBox(邮箱)里(你可以简单理解为一个队列), 然后 Actor 从 MailBox 捞数据, 一条一条顺序的捞
然后不同的 Actor 则并行着处理一样的事情
由于大家都是互相独立的处理各自的事情, 数据不会发生冲突, 也就无需类似锁之类的机制来确保数据一致性问题
由于 Actor 类文章网上搜索一大片, 在此就不再过多阐述了.
什么是奥尔良?
简单一句话, 微软的一个基于 Actor 模型的实现, 具体介绍可以更多参考官网
奥尔良官网
他跟正儿八经的 Actor 相比, 微软习惯就是将其做更加上层的封装, Actor 都变成了 Grains, 万事万物皆是 Grains 的感觉
我干了什么?
我也刚开始入门, 发这篇文章主要是想证实下, Actor 那套是不是真的那么神, 本文涉及的所有代码均在 上面
既然他们说他们是以单线程来处理同一个 Actor, 那我就想测试下用 Orleans 搞一个并发转账的场景, 和我常规的多线程并发转账场景的一个对比, 而我想看到的结果是, 常规版的由于多线程的问题数据总是错乱的, 而奥尔良则能始终正确
转账代码
我有一个账户, 账户上面有 Money, 我能做 2 个操作, 要么转钱过来, 要么查看我还有多少钱, 当然, 转账总要点时间的对吧, 所以转账时候 Delay 了 1ms
实际转账的执行代码
可以注意下奥尔良版和原始版唯一区别在于
奥尔良版是通过 client.GetGrain 来获取了一个 IAccount, 这样获取到的是属于奥尔良托管的一个 Client 实例, 对其执行的操作其实会发送到 Host 里执行, 然后 Host 里就是正儿八经的 Actor 架构来去处理所有操作
但是正如之前介绍 Actor 的时候谈到单个 Actor 是单线程, 而多个 Actor 之间是并发, 如何确定你是一个还是多个 Actor, 是通过一个 Id 来区分(具体奥尔良官网有介绍), 而 GetGrain 后面的那个 0 的参数就是他的 Id, 也就是我的这个 IAccount 是属于一个 Actor
常规版直接 new 一个实例执行同样操作
然后代码运行, 可以看到结果
原始版的结果仅供参考, 我每次运行得出来的结果也都不一样(多线程执行顺序是不确定的)
而奥尔良版则能正确的恒定输出 4950
至此, 可以明确奥尔良完美的实现了 Actor 里关于单个 Actor 单线程的这么个处理....
来源: https://www.cnblogs.com/leolaw/p/10546239.html