关于重新设计data accessing layer的思考(一)
背景:项目中已运行10年的数据访问层,存在若干架构方面的问题,为了彻底解决并释放并行访问的能力,并提供一套完整的面向对象的API,决定重新设计。
思考问题:
1.如何保证兼容性:
1)使用新库的实现替代旧库中的实现,保证一次性全部修改并测试,不修改旧库的API,且提供用户新的API
2)新库与旧库完全隔离,同时存在,但新库需要保证与旧库的数据同步。旧库不做任何修改。用户可以同时使用新库和旧库
2.如何保证多线程访问的效率:
1)一直以来,内存和CPU总会出现冲突,在数据访问更是如此。当动态数据在内存中只有一个存储地址,必然在多线程访问中需要各种同步机制,或者异步访问而影响到效率。如果牺牲内存,提供内存的duplication,那么存在的问题,变为了内存的使用量double,并且需要merge这些修改,或者是duplication。实际上,数据库的设计中,对这个问题提供了多种的解决方式,比如snapshot。实际上这种思路在旧的Data Accessing Layer的设计中,也体现了一些,当时一开始数据存在内存中只有一份,但运行时发现在多线程或者多进程的条件下,使用锁的机制,无法完全发挥多线程的优势。后来只能采取通过数据的多个备份,来保证多线程的效率。当然每个备份就需要相互之间的数据同步,这也就造成了一个问题,就是当出现conflict怎么办的问题。最初,我认为,将数据放在share memory中大家一起共享,似乎是一个最方便且最有效率的方法,但越来越发现,如果想充分发挥多线程或者多进程的效率,应该考虑的是如何在内存使用量和CPU效率之间做一个权衡。
2)减少数据的互斥性,特别是对于动态数据。修改数据库中Data Model,保证表中的数据均为运行期产生的动态数据(对于现有数据中,80%均为静态数据),将静态数据存入sharememory, 给所有进程共享,并且使用单独进程preload. 对于动态数据,特别是字符串数据,能够使用enum进行映射就应该从数据库中移出。
3)每个线程当访问时,会创建一个独有的数据的snapshot,这样,当线程需要提交修改时,将自己决定如何处理conflict.
(待续)