Orleans之EventSourcing

引入:

    如果没有意外,我再这篇文章中用ES代替EventSourcing,如果碰到"事件回溯","事件溯源","事溯"等词语,都一般代表Eventsourcing.

    如果引入Orleans而不用es的话,那就只用了Orleans一半的优点,多线程编程的逻辑\排错的简化以及可分布式.下面我聊聊重头戏ES,这些都是我个人理解,如果有错误欢迎指正.

    有时候产生一个理论是为了解决目前的困难,但是随着事物的发展,原先的困难不再是主要困难,新的夜王必然会出现,听闻三眼乌鸦要成为新的夜王我很是不解.马丁这么写会收到愤怒的读者寄来的刀片,我估计马丁把收到全世界的刀片都卖了,都比他的小说值钱.扯远了。总而言之,我们关注的矛盾点会随着时间变化而变化。以前为了节省存储空间(当然并不仅仅是为了空间考虑),对数据库的设计提出了三个范式,来指导数据库的设计.可是现在时代变了狗蛋,存储空间不值钱了.现在数据库读写成为了新的瓶颈,所以我们设计数据库的理念就应该变了.

    ES遵循这一个简单的思想,就是存储的时候只存储变化量,而不存储最终结果.需要最终结果的地方,就必须提取所有的变化量以及初始状态,让它们相加得到最终结果.这样的看起来是个麻烦的迂回(我不就是想得到最终结果嘛),但是却隐藏着一个事实:由于只存储变化量,意味着数据只增不减,意味着数据存储后就不会被更改,意味着高并发和高吞吐量.但是有个缺点就是数据量增加很多,现在硬盘是最不值钱的,如果随着时间的推移,变化量变的很多,要得到最终结果需要大量的运算,但是.这些缺点不算什么大缺点,有方法可以避免.虽然一直说空间不值钱,并不是说数据大小无关紧要,在合理的设计中,数据应当能小则小.

    简单的一句总结就是满足只增不减,存后不改的数据,都能够设计成ES.以便于提高吞吐量.

    为啥只增不减会提供吞吐量?因为数据库的数据永远不变,所以就放心大胆的读取吧。哪怕是多线程都不需要架锁。可是这里隐藏着另一个风险,你读取的数据不一定是最新的。这个"非最新"的确是个难题,不过好消息是,如果你一直读,最终能够读到最新的。这就是"最终一致性"。

    关于es网络上有很多的文章,可以拿来读读,这里就不做过多的叙述了。

    Orleans内置了三种ES的实现方式,但并不是我提到的ES.它内置的三种ES实现方式,分别是:StateStorage.LogConsistencyProvider,LogStorage.LogConsistencyProvider和CustomStorage.LogConsistencyProvider。这里我只使用介绍官方例子,它使用的是CustomStorage这个类。

    使用Orleans达成ES,要明白几个基本的概念,所谓的Event是个啥东西?在Orleans中Event一般是指的自定义的grain事件,这些事件的发生更改了grain的状态。笼统的讲就是更改了grain类相关的各种变量的值。那么你要把这些值存起来,就要问两个问题,存到哪里去,用哪个类来控制存。又要要求溯源,那就必须读,那就要解决用什么序列化的问题。这本质上是一个问题:用什么类控制存储。

    我打算拿官方的例子来介绍一下ES在orleans中基本实现方式。看完介绍,如果读者要实现自己的ES,可以仿照更改。Orleans源码里有一个例子是ReplicatedEventSample(以下简称RES),这个是我下面要说的重点。

    RES例子是一个网页例子,它的网页如何体现的,以及如何运行RES,我将不做介绍,这里我只是重点说明网页后边的支撑程序:就是以下三个项目

    

    其中主要设计的类总体图像如下:

    EventGrain是这个项目的主角,它接受到外界发送来的一些消息,把这些消息使用ES的方式存储下来。在使用RES的时候,要注意EventGrain的基类以及需要实现的接口。

    EventState是Grain的状态值。

    ReplicatedEventTable控制着实际的读取与存储。

    GeneratorGrain一个消息制造器,它发送OutCome消息给EventGrain

    TickerGrain,可有可无的东西。

    它们工作流程如下

    刚开始启动的时候,silo会调用GeneratorGrain,这个GeneratorGrain的n个实例会激活EventGrain并每2.5秒发送一次OutCome消息。如下图

    

    EventGrain接受到激活指令后初始化一个ReplicatedEventTable实例用来控制自己的存储,并调用RefreshNow()获取最新的状态,这时候orleans会调用ReadStateFromStorage,EventGrain在这里使用ReplicatedEventTable完成真正的读取动作。

GeneratorGrain每隔2.5秒制造一个OutCome消息发送给EventGrain,EventGrain接受到消息并立即确认此消息,这时候可以在OnStateChanged函数中针对Grain状态值变化做一些必要的处理。这些必要的处理不应该包括ES存储动作,ES存储动作会在ApplyUpdatesToStorage中进行处理,它里面使用了ReplicatedEventTable来进行真正的存储。

    这样一个简单的ES就实现了。这个ES里面的每一条数据都是OutCome,我们只需要改写ReplicatedEventTable实现自己的存储控制类。在本例子中,使用的是AzureTable作为存储媒介的。

    这里有几个问题,如果我改写后的新存储控制类,假设名字是EventSql是一个普通类,在EventSql中我精确的控制了sql连接,sql读取等等。因为EventGrain是一个key一个实例的。在一个soli中有可能存在非常多个Grain实例,这时候我再使用EventSql就有可能会产生很多的链接,导致出错。要改进这里,只需要让EventSql本身也是扩展自Grain(而不仅仅是一个普通的类)。同时使用一些机制来控制链接数。可以池化这些EventSqlGrain,使用的时候从池子中取出一个。

    这样官方的例子就算介绍完毕了,剩下的来聊聊一些其他细节的问题。

    Orleans运行时会时不时的自动更新Grain的状态值。但是有时候也是需要针对某些事件,我们自定义的去更新状态值,要实现这样的动作,可以重写TransitionState 函数。

    ReadStateFromStorage返回的值中需要有version 和对应的State。刚开始的时候,压根什么都没有存,那么就应该返回0和一个State的默认值。ApplyUpdatesToStorage有时候会存储失败,这时候运行时会进行重试。有时候虽然状态值已经实际存储了,但是却返回一个错误,这样会造成同一状态值的重复存储,这里就需要程序有一个过滤机制或者确保一个重复的状态值不会对程序逻辑造成损害。

    使用Orleans.EventSourcing.CustomStorage.LogConsistencyProvider(本例就是),它并不支持JournaledGrain类中的RetrieveConfirmedEvents方法,如果需要使用它,要另行实现。

这里只是我个人写一些基础的东西,具体改写还是需要自己去实现,刚开始可以仿照这个RES进行改写,把OutCome存储到自己想要的地方。等改写完毕就会一个大致的概念。

至此我写完了orleans所有的主要方面,剩余的orleans底层的实现细节,还是需要自己对照文档啃源码了。

    ES是实现业务需求的方法,一个项目本身是一个客观物体,我们选择了使用ES的办法去实现它,会将这个项目的复杂度进行转移,降低了业务在程序实现上的复杂度而同时增加了数据设计的复杂度。ES这个新的方法会让某些复杂的业务逻辑变的简单,特别适合于那些需要高并发与高吞吐量的场景。

开篇曾经说过的,"如果随着时间的推移,变化量变的很多,要得到最终结果需要大量的运算"是个缺点,要克服这个缺点,可以这样搞:每隔一段时间(比如一周)就计算所有的最终结果,并把这个最终结果当作新的初始值,同时把变化量转移备份。简单的如下图所示:

原文地址: http://www.cnblogs.com/gaopang/p/8457990.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/322085.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Alex: 2018年对混合现实MR的展望

原文作者:Alex Kipman, 微软操作系统工程院技术院士 Hello 大家好!难以置信我们已经走过了2018年的头两个月了。每年一月份我都会去巴西省亲,和我的家人欢聚一堂,度过一个美好的假日。在我省亲的同时,我想了…

jzoj3738-[NOI2014模拟7.11]理想城市(city)【树,模型转换】

正题 题目大意 一个理想城市有nnn个块构成,有以下性质 任意两个块之间可以通过其他块到达任意两个块之间可以不通过其他块(通过空位)到达 然后求每个块之间的距离之和。 解题思路 我们将横竖的距离分开计算。 假设现在我们考虑计算竖向的边的距离,我…

SpringCloud Ribbon(二)之自定义负载均衡策略IRule

一、Ribbon负载均衡策略 一个服务对应一个LoadBalancer,一个LoadBalancer只有一个Rule,LoadBalancer记录服务的注册地址,Rule提供从服务的注册地址中找出一个地址的规则。 Ribbon提供七种负载均衡策略,默认的负载均衡策略是轮训策…

欢乐纪中A组赛【2019.8.10】

前言 昨天: MdMdMd今天还真爆零了 顺便%%%ZZYRank1\%\%\%ZZY\ Rank1%%%ZZY Rank1 成绩 JJJ表示初中,HHH表示高中后面加的是几年级 RankRankRankPersonPersonPersonScoreScoreScoreAAABBBCCC111(H−1)ZZY(H-1)ZZY(H−1)ZZY1501501502020203030301001001…

Blazor正式成为Microsoft官方.NET 和WebAssembly项目

Microsoft从Blazor的开发者Steve Sanderson手中接手了这款应用程序,自此,将.NET在浏览器运行的计划又更进了一步。由此,Microsoft又进一步扩充了自己的WebAssembly/.NET栈,更进一步帮助.NET开发人员搭建基于浏览器的应用程序。在一…

SpringCloud Ribbon(一)之自定义负载均衡器ILoadBalancer

一、Ribbon负载均衡 一个服务对应一个LoadBalancer,一个LoadBalancer只有一个Rule,LoadBalancer记录服务的注册地址,提供更新服务的注册地址,Rule提供从服务的注册地址中找出一个地址的规则。 二、 自定义负载均衡 本文自定义负…

.NET Core 2.1路线图

Microsoft的Scott Hunter发布了Microsoft .NET Core 2.1版本的路线图。Hunter宣布Microsoft .NET Core每天约有五十万开发人员的使用量。根据Microsoft所收集的数据,在2017年9月.NET Core 2的使用量已经超过了.NET Core 1.X。有了之前成功的发布经验,Mic…

SpringCloud Ribbon(三)之IPing机制

一、IPing机制 IPing是一个主动探测服务节点存活的机制,通过判断服务节点的当前状态,设置节点的可用状态。只有当节点为可用时候才会作为负载均衡器的选取节点。 IPing有以下几种模式: DummyPing:默认返回true,即认为所有节点都…

.NET Core使用swagger进行API接口文档管理

一、问题背景随着技术的发展,现在的开发模式已经更多的转向了前后端分离的模式,在前后端开发的过程中,联系的方式也变成了API接口,但是目前项目中对于API的管理很多时候还是通过手工编写文档,每次的需求变更只要涉及到…

.NET下使用socket.io随笔记录

一、问题背景目前公司在互联网产品上需要程序与前端部分要进行一个实时交互,在进行一定程度上的选型后,决定使用socket.io框架进行一个实践,算是公司的一个新的 尝试,也算是给自己增加增长见闻,由于我是做后端以及桌面…

SpringCloud Ribbon(五)之服务实例列表ServerList

一、服务实例列表ServerList 服务实例列表(ServerList)为负载均衡器(Loadbalancer)提供服务的可用实例列表。 负载均衡器(Loadbalancer)通过服务实例列表(ServerList)从注册中心&a…

超级简便的容器化部署工具(使用 ASP.NET Core 演示)

Docker 改变了我们部署网站的方式,从原先的手动编译打包上传,到现在的构建镜像然后推送部署,让我们在配置环境上所花费的时间大大减少了。不仅如此,通过一系列相关的工具配合,可以很轻松的实现 CI、CD。本文即将介绍的…

学习手记(2019/7/05~2019/8/31)——快乐暑假

文章目录二分答案的作用堆和区间很糙ddp线段树合并网络流结论の1树上莫队对角线与GCD区间与扫描线与方案数欧拉欧拉*1斯坦纳树切比雪夫距离二分匹配结论の1min-max容斥计算几何の -1二分答案的作用 求最大值最小ororor最小值最大将求值问题转换为判断问题在判断问题之间相互转…

SpringCloud Ribbon(六)之服务实例过滤器ServerListFilter

一、服务实例过滤器ServerListFilter 服务实例过滤器(ServerListFilter)为负载均衡器(Loadbalancer)提供从服务实例列表(ServerList)获取的服务实例过滤出符合要求的服务实例。 负载均衡器(Lo…

听说你开发.NET还在用VS,小哥哥给你推荐全平台的Rider

前言.NET平台的开发一直都只能使用Visual Studio来开发,自从dotnet core 发布后不久,jetbrains 发布了Rider预览版,到目前为止的正式版2017.3.1。博主都使用过,因为博主的主力开发语言是C#,所以一直以来被捆绑到Window…

给Ocelot做一个Docker 镜像

写在前面在微服务架构中,ApiGateway起到了承前启后,不仅可以根据客户端进行分类,也可以根据功能业务进行分类,而且对于服务调用服务也起到了很好的接口作用。目前在各个云端中,基本上都提供了ApiGateway的功能&#xf…

.NET Core UI框架Avalonia

.NET Core UI框架Avalonia,Avalonia是一个基于WPF XAML的跨平台UI框架,并支持多种操作系统:Windows(.NET Framework,.NET Core),Linux(GTK),MacOS&#xff0c…

揽货最短路径解决方案算法 - C# 蚁群优化算法实现

需求为(自己编的,非实际项目):某配送中心进行揽货,目标客户数为50个客户,配送中心目前的运力资源如下:现有车辆5台单台运力最大行驶距离200千米单台运力最大载重公斤1吨问:运力怎样走…

OIDC在 ASP.NET Core中的应用

我们在《ASP.NET Core项目实战的课程》第一章里面给identity server4做了一个全面的介绍和示例的练习 。如果想完全理解本文所涉及到的话题,你需要了解的背景知识有:什么是OpenId Connect (OIDC)OIDC 对oAuth进行了哪些扩展?Identity Server4…

论文阅读:Blind Super-Resolution Kernel Estimation using an Internal-GAN

这是发表在 2019 年 NIPS 上的一篇文章,那个时候还叫 NIPS,现在已经改名为 NeurIPS 了。文章中的其中一个作者 Michal Irani 是以色 Weizmann Institute of Science (魏茨曼科学研究学院) 的一名教授,对图像纹理的内在统计规律有着很深入的研…