昨天晚上未加班,回家继续albian。发现了两个问题。
目前albian已经可以简单的保存数据了,albian提供了2个create的重载:保存一个实体、保存多个实体。在保存一个实体的时候未发生问题,数据能准确的根据路由保存到我们指定的数据库和表。在保存多个实体时,开始测试了保存两种不同的实体:比如一个order、另外一个bizoffer,也不会出问题。但是在保存两个相同类型的实体时(比如两个order)。就发生了问题:后面的一个实体数据会覆盖掉前面的一个实体数据。开始怀疑是不是在分配storagecontext的时候出错了,后来debug未发现;再怀疑是不是sql语句出现了问题,debug后还是未发现问题;只能看代码,发现自己在建模的时候就已经犯下的错误。在我当初的建模中,storagecontext中的cmd和paras是使用IDictionary<string,dbpara[]>结构来存储的,当时的想法是:一个cmdtext对应一个它自己的参数;这样IDictionary结构正好可以满足要求,但是这种情况,如果发生在cmdtext相同的时候就会出问题了,因为我做了替换的操作,所以后面的实体会更新掉前面的实体数据。其实自己傻掉了,但是cmd-paras的结构是有实体类承载的,这边只要改成IList即可。重构代码,test用例一遍走过,没问题了。
第二个碰到问题的是albian的代码结构问题。开始的时候,我想对DML的操作创建一个接口,然后不同的操作实现这个接口。但是经过create的代码重构,发现除了拼SQL部分的代码不一样之外,别的代码都一模一样。这样的话,这个接口就一个方法(比如叫GetSql),开始感觉还行,但是怎么的越看越不顺眼,后来一想,一个方法的接口不就是委托嘛?全部改成委托,每个实现方法按照委托的签名编写,然后通过参数传递进去不就剩下了很多代码吗?还省下了继承接口这种体力活。这样,这部分也改成了委托。
问题解释:
就上一篇文章中提到的“伪分布式事务”问题进行一下解答。albian使用的事务管理是每个数据库一个事务,然后分步操作,等全部操作完成后分步提交的方式。这种方式确实会存在一定的风险性。可能出现问题的地方是如果我们有2(A,B)个操作需要提交。当我们提交了A之后再提交B。如果在这两个操作中间(提交了A,正要提交B)发生了网络的中断或者B机器的down机,那么我们的程序将会rollback事务。但是对于A而言,操作已经被commit了,已经成了永久存储,无法被rollback,这样我们的系统中就出现了脏数据。对于这种情况,我们可以根据情况进行补救,比如在保存之后判断是否操作正确,不正确的话执行一段补救代码。但是对于一般的系统,并不需要这样做。类似于刚刚的操作问题其实只有在分布式系统的情况下才可能发生。对于分布式系统,对于单节点的CAP理论已经不能适用了。你必须放弃CAP中的任何一种特性,满足剩下的两种特性。albian放弃的是一致性,其实你分析事务那段源代码很容易就能得出我们使用了“最后一致性”来保证数据的完整性。在分布式系统中,一般对于数据的完整性要求不那么高,至少不会是100%。高的可能是99。99%,低的可能是95%,甚至还有更低的。当然这些指标数据只是对于一段时间内(比如一个数据库的访问,或者一个用户对于系统的访问)的数据完整性而言,最后我们还是会通过复制、同步等等外在的方法来达到系统内的数据一致性。
就CAP理论在分布式系统中的使用,请g之!