全部博文(2065)
分类: 数据库开发技术
2010-06-19 17:50:35
数据访问层开发实践
许超前@手机之家
1. 关于数据访问层(DAL)
我的理解:有了这一层东西之后应用开发人员其实是不需要关心底层是用什么数据库怎么分库、分表。底层的API到底是什么东西实现的。走的是什么FS等等。
PS:目前我的研究领域也是基于这个想法。另外可能更关注的是底层的分布式缓存实现即数据库层面准确的是讲在DB与DAL之间的一个分布式缓存实现。
关于DAL
1) 不但具备了memcached和mysql proxy的优点,还避免了两者的缺点。
2) Dal作为一个中间件,应保持语言中立、数据库中立。
3) 让系统在数据访问层上具备分布式计算能力。
4) 不造ORM轮子,只是发明访问数据的接口。
关于Dal - 核心概念
1) 透明
分片透明,缓存透明,主从透明。
2) 虚库(逻辑库)和实库(物理库)
虚库:不是一个真正存在的库。也叫逻辑库。
实库:是真实存在的库。也叫物理库。
3) 虚表(逻辑表)和实表(物理表)
虚表:不是一个真正存在的表。也叫逻辑表。
实表:是真实存在的表。也叫物理表。
4) 分片(分表)
分片可以分布在同一个库中,也可以在多个库中。也叫分表。
关于Dal - 核心概念(续)
5) 映射
虚库 → 实库;
虚表 → 实表;
应用列名 → 数据库列名;
6) 条目缓存和查询缓存
7) 辅助索引
8) 分片情况:不分片、分片无辅助索引、分片有辅助索引
9) 面向库的开发方式
这是指,Dal自动从数据库获得需要的信息,而不是由应用开发人员在配
置文件里显示配置。开发人员要配的只是分表的规则、连接池的使用、缓
存的使用等。只在应用层需要和数据库不一样的信息时(如字段名),才
在配置文件里显式写出。
我的理解:定义一个配置库(配置表)。然后应用开发人员就从这个配置表里面读取所需要的信息然后进行操作相应的DB。
Dal的产生 - 多数现有系统的经典问题
1) 由于web server可以直接访问db server,在高峰阶段,并发量比较大,导致db
server经常down掉。
2) 添加缓存代码以降低数据库访问压力,但由于开发人员自己控制缓存使得:
a)缓存访问逻辑混杂在系统的各个角落,造成代码维护成本上升。
b)开发人员根据自己的喜好来控制缓存的KEY和VALUE,造成缓存混乱。
c)开发人员既要负责业务逻辑的编写,还要负责缓存管理,造成编程复杂度提高、开发效率低下。
3)在分表的情况下,程序员需要考虑和编写大量繁杂的和分表有关的代码:
a)需要根据规则计算出数据的存取目标是在哪个分表当中。
b)如果取回的数据分布在不同的分表中,需要合并结果。
c)由于大表切分后变成了多个小的分表,对于有排序要求的查找,
需要通过建立并查找辅助索引来解决。
d)如果一套分表有多个辅助索引,需要寻找最优辅助索引。
Dal的产生 - Dal1.0的典型用法
接口采用API Invocation+Call Chain的方式,所有的方法名取自
SQL关键字,方便记忆。
1)增:DataAccessor::insert()
->table('imobile.post.db_post')
->data(array('post_id'=>1,
...))
->dup()
->execute();
2)删:DataAccessor::delete()
->table('imobile.post.db_post')
->where('post_id', 'IN',
array(1, 2, 3))
->limit(3)
->execute();
3)改:DataAccessor::update()
->table('imobile.post.db_post')
->data(array('level'=>0))
->where('user_id',
'<', 1000)
->limit(100)
->execute();
4)查:DataAccessor::select()
->table('imobile.post.db_post')
->columns('post_id')
->where(array('thread_id'=>1,
'forum_id'=>2))
->getAll();
测试结果:
Dal1.0使得数据库的QPS从几千降到几百,缓存命中率稳定在60%~80%
之间。
Dal1.0还标准化了调用接口,简化了编程,使程序员在业务逻辑层面不再
关心缓存与分表问题,极大地提高了生产力。
成效:
Dal1.0使得数据库的QPS从几千降到几百,缓存命中率稳定在60%~80%
之间。
Dal1.0还标准化了调用接口,简化了编程,使程序员在业务逻辑层面不再
关心缓存与分表问题,极大地提高了生产力。
我们自己编写一套DAL层的Server与客户端的代码。应用开发人员只需要下载客户端的包就可以使用全部的API与服务层进行通讯。另外我们的服务层使用了自己编写的缓存组件。
这样的应用人员不需要关心底层到底是什么存储的。全部走我们的这套API调用。
看到没有。这就是这个服务层的整体的框架。里面包含了query parser即用户丢过来一个数据查询的语句我们到底如何解析即SQL转义处理。然后有一层dal handler这个主要应该是与客户端通讯用的。
在增、删、改、查四类查询当中,Dal2.1.x都比Dal1.0有了很大的提升。
原因在于:减少了一次socket请求、采用了异步消息处理机制、引入连接池及优化了算法等等。
相关的问题
1) Dal2.1.x采用的是内置缓存,而且存放的数据结构也不好(大量的Map及字符串),在缓存数据量大的情况下,JVM不堪重负,将进行频繁的GC。在高峰情况下,甚至会出现全GC,这时客户端connection timeout就频繁出现了。
2) 不支持分布式事务。这使得在分片分布在多个库的情况下,数据的完整性得不到保证。而跨查询事务问题更是得不到解决。
3) 不能简单的支持数据库主从。
4) 缓存不能简单地进行外置。
5) 不好在高峰时段进行配置Reload。
6) 不管分不分片,都得写一大堆配置。
7) 内置消息队列占用太多内存。
8) 不能把dal作为嵌入式包来使用。
进一步发展:
变更
1) 自动生成条目(实体)类,用于缓存数据库记录。数据已经有了类型,同时有望缓解JVM GC问题。
2) 支持分布式事务。遵循XA规范。
3) 支持数据库主从。
4) 缓存内置、外置,任君选择。
4) 更好的元信息抽象,更聪明的发现及重载机制。
5) 更优的内置消息队列。内存中存储的是引用。
6) 已从Dal Server分离出Dal Core,可以简单地作为嵌入式包来引用。
7) 已支持Php, Java, Python, Ruby四个客户端。
进一步发展
1) 继续完善功能、提升性能;
2) 支持Spring、Guice集成;
3) 支持更多的数据库,如PostgreSQL, DB2等;
4) 集成全文搜索功能;
针对不同的后端数据库(到底是什么类型的数据库完全由应用来决定的)。编写各自的一套API吧?
PS:目前我正在写一套基于内存的数据库。将来这个可以应用到缓存模块中去。努力要自己写一套这样的东西出来。加油啊!
chinaunix网友2010-06-21 20:39:49
我相信只要我肯定珍惜好现有的时间,不要浪费时间把精力投入到自己的领域上面肯定会有点成绩的。我希望能够在互联网领域做一番事业