Warning: mysqli_num_fields() expects parameter 1 to be mysqli_result, boolean given in /www/wwwroot/dev.zhalaotie.com/wp-includes/wp-db.php on line 3215

Warning: mysqli_num_fields() expects parameter 1 to be mysqli_result, boolean given in /www/wwwroot/dev.zhalaotie.com/wp-includes/wp-db.php on line 3215
ORM 设计:缓存 线程安全 数据库事务与编程式模拟事务 读写分离 队列(2013 年) – 扎老铁
Warning: mysqli_num_fields() expects parameter 1 to be mysqli_result, boolean given in /www/wwwroot/dev.zhalaotie.com/wp-includes/wp-db.php on line 3215

Warning: mysqli_num_fields() expects parameter 1 to be mysqli_result, boolean given in /www/wwwroot/dev.zhalaotie.com/wp-includes/wp-db.php on line 3215
Warning: mysqli_num_fields() expects parameter 1 to be mysqli_result, boolean given in /www/wwwroot/dev.zhalaotie.com/wp-includes/wp-db.php on line 3215
class="post-51989 post type-post status-publish format-standard has-post-thumbnail hentry">

ORM 设计:缓存 线程安全 数据库事务与编程式模拟事务 读写分离 队列(2013 年)

缓存 线程安全 数据库事务与编程式模拟事务 读写分离 队列

2012121

9:23

对于 更新修改操作,全部是在内存中进行的。

 修改了一条数据,不一定会立即提交到数据库

 而是压入队列中,这样可以保证性能。

 

 对于缓存的操作,让读并发,写入串行。

 

 原本可以做到对这些做好控制

 但现在,用了NHibernate 很多 底层的被封装掉了。

 只能 从 NHibernate提供的API入手

 

 最最大大问题就在于如何控制NHibernate

 而NHibernate又实在太强大,必须用。

 

 还有一个最大的问题,这样的架构,都需要是N个数据库才行的,因为万一一个数据库挂了,队列里面的数据就没法成功持久化进数据库。

 

 但是,我想也不是完全无解,有人说,记录住事件而不是数据。

 参考banq大叔的说法和lamx架构。

 如:对User对象的Point属性加了1,记录下这个事件。

 但是不更新数据库。不管它。

 事件记录了,写入磁盘或内存中。

 

 那么,无论数据库宕机,还是应用服务器宕机,都没有关系。。

 因为,在服务器恢复正常的时候,回放事件,将事件再转化为数据。

 

 不知道,我对lamx架构的事件回放的理解 是否正确。

 

 

 ===

 QA:

 Q:为什么不立即提交更改到数据库?

 A:慢。数据库更新,可能会造成粗粒度的锁表,对并发不好。而在内存中更新,只需要锁住内存中的精确的某个对象,甚至很多操作不需要锁。

 

 

 Q:数据的更新没有即时提交到数据库,那么未来的读取中,是否会取到脏的数据?

 A:不会。因为每次SQL查询都会被解析,如果缓存中有的记录Id,就用缓存中的对象返回出去。

 如果缓存没有,就证明是新数据,将db数据展开成对象,放入缓存。

 

 缓存会定期清理的,在清理的时候,未持久化到数据库的更改会被提交。

 

 

 

 

 

 

演变

 

 

内存事务锁模型。

 非常小粒度的锁。

 

 目前 只是模拟了类型数据库事务的 阻塞机制,要开启事务,就会事先锁定好 事务中将会修改的对象。

 

 

 

 

 

今天对事务模式增加了

 针对外部读的锁机制。原本只有事务和事务之间的相关实体对象能锁住,以保证更新操作的原子性。 但是却没有对外部的读取加锁,这样会产生”脏读“。

 完成了 ”回滚“内存事务对实体类更改的基础骨架。思路很简单,配合前面的 锁机制,保证只有事务内才能更改实体的数据,但是此时的更改并不是直接提交到实体中,而是被拦截并记录了下来。所有对实体类所有属性的读/写都不是直接读写的,而是通过中间层来控制。

 当事务成功提交的时候,再将记录到的更改合并到真正的实体中。对象的引用不变,改变的是属性的值。

 

 这样,内存事务的好处真的就体现出来了。

 数据库事务默认 是你更改了哪张表的数据,就会锁住整张表,SQLSERVER可以在SELECT后面加 NOLOCK跳过锁表。

 其它的锁模式,没有试过。不过关系型数据库的锁和事务是很有用的。

 namespace System.Data

 {

     // 摘要:

     //     指定连接的事务锁定行为。

     public enum IsolationLevel

     {

         // 摘要:

         //     正在使用与指定隔离级别不同的隔离级别,但是无法确定该级别。

         Unspecified = -1,

         //

         // 摘要:

         //     无法覆盖隔离级别更高的事务中的挂起的更改。

         Chaos = 16,

         //

         // 摘要:

         //     可以进行脏读,意思是说,不发布共享锁,也不接受独占锁。

         ReadUncommitted = 256,

         //

         // 摘要:

         //     在正在读取数据时保持共享锁,以避免脏读,但是在事务结束之前可以更改数据,从而导致不可重复的读取或幻像数据。

         ReadCommitted = 4096,

         //

         // 摘要:

         //     在查询中使用的所有数据上放置锁,以防止其他用户更新这些数据。防止不可重复的读取,但是仍可以有幻像行。

         RepeatableRead = 65536,

         //

         // 摘要:

         //     在 System.Data.DataSet 上放置范围锁,以防止在事务完成之前由其他用户更新行或向数据集中插入行。

         Serializable = 1048576,

         //

         // 摘要:

         //     通过在一个应用程序正在修改数据时存储另一个应用程序可以读取的相同数据版本来减少阻止。表示您无法从一个事务中看到在其他事务中进行的更改,即便重新查询也是如此。

         Snapshot = 16777216,

     }

 }

 

 

考虑到性能,这个内存事务模式增加了两种锁定模式。这样,开发者可以指定,开启的事务时需要锁住外部的读和写以保证数据一致性,还是只锁住外部的写入,以保证性能。外部的相关操作被锁住之后,外部线程会进入自旋等待(目前是自旋锁模式,也许Yield更好,这个真不确定)。

 

 /// <summary>

 /// 在事务中指定的的所有实体对象上放置锁,以防止其他用户读取或更新数据。

 /// </summary>

 ReadWrite,

 /// <summary>

 /// 在事务中指定的的所有实体对象上放置锁,以防止其他用户更新数据。但可以进行幻像读。

 /// </summary>

 ReadUncommitted

 

 

但是其实框架为开发人员解决了很多原本很麻烦的事情。也做了很多,还有一些没有时间去做。每经历完一个紧张的项目,都会发现新的需要改进的地方。第一次是弃用了自己写的ORM,不再需要继承基类。改为接口+扩展NHibernate。WEB端的模式基本不变,但新提出了页面异步处理模型,这时候ORM还不足以支撑这个模型。没有查询计划。

 新增了包装器。作为完全自动化处理表单数据。

 这一次,最大的改动还是ORM。向DDD和一些革命性的理念靠近 没有实践是不行的。没有框架,就无法让大家掌握。

 

 

======

 技术相关帖。

 并不是什么事情都异步就会性能好的,过多的线程数量会造成线程间频繁的切换。

 我也认同,经过实践,对于那些很快就能完成的事情,不要开启线程。那会损伤性能。

 对速度不是要求很高的地方,即使多线程能提升性能,也不一定要用多线程,有些地方 配合缓存,就可以取代异步。那样只会第一次发生的时候慢一点。但却节省下了宝贵的CPU资源。内存是比较便宜的。

 

 设计的时候 就要考虑各个操作之间的依赖性。尽量使 耗时的相关操作以原子化的方式实现。这样以后可以轻易地切换为多线程模式。

 

 

 

 

已使用 Microsoft OneNote 2013 创建。

发表评论

电子邮件地址不会被公开。