目前已归档公文查询现状
a) 数据库结构不合适。由于需求要求每个用户只能查询自己能查的公文,但标识一个公文可以被哪个公司、部门或个人可查的字段,却不存在,必须使用Like语句来匹配,极大的增大了表的扫描范围,增大了数据库IO、内存开销,降低了查询速度。
b) 查询结果集取出全部数据,直接导致数据库IO、内存、网络资源增加。同时由于在WebService层创建完所有对象后,再进行分页,然后取出指定一个页面的结果集返回,使数据流的使用效率几乎为0。
分布式缓存MemCached介绍
memcached是由Danga Interactive开发的,高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。memcached使用了libevent(如果可以的话,在linux下使用epoll)来均衡任何数量的打开链接,使用非阻塞的网络I/O,对内部对象实现引用计数(因此,针对多样的客户端,对象可以处在多样的状态), 使用自己的页块分配器和哈希表, 因此虚拟内存不会产生碎片并且虚拟内存分配的时间复杂度可以保证为O(1).。
分布式
memcached的缓存是一种分布式的,可以让不同主机上的多个用户同时访问, 因此解决了共享内存只能单机应用的局限,更不会出现使用数据库做类似事情的时,磁盘开销和阻塞的发生。
所以,如果有多台计算机需要缓存相同的东西,才需要使用分布式缓存。
基于键值对
memcached使用了同样的“Key=>Value”方式组织数据。同时不提供Key的枚举操作,只能使用相同的数据Key生成规则来生成访问指定Value的Key。
数据淘汰算法
memcached采用了一种"懒过期"的策略,这种策略不消耗额外的CPU时间去专门处理过期的item。当一个item被请求(get命令)时,memcached会检查这个item的过期时间;如果已经过期,这个item将不会被返回给客户端。
同样,向cache中添加一个item时,如果cache已经满了,memcached首先替换已经过期的条目,然后替换最近未使用的item(the least used item, LRU淘汰算法)。
缓存查询结果集提高翻页效率
现实状况中,由于已经对05、06、07、08、09年的公文进行归档,所以归档数据库中含有历年数据。如果进行数据库结构调优,所以风险大收效小,所以暂不进行优化。
目前已经实现使用MemCached对查询的结果集进行缓存,以加速翻页效率。
l 序列优化
在结果集缓存方案中,主要步骤及用时权值为:
序号 |
步骤名称 |
时间复杂度 |
依赖 |
1 |
缓存主键生成 |
1 |
|
2 |
查询缓存 |
3 |
1 |
3 |
数据库查询 |
1000 |
|
4 |
数据库网络IO |
50 |
3 |
5 |
生成分页 |
30 |
4 |
6 |
缓存分页 |
200 |
5 |
可以看出,数据库查询最慢,其次是把分页后的记录缓存到MemCached次之。
有鉴于此,在实现方案上,使用了多线程技术,下一步骤操作只要依赖步骤完成或部分完成,立即开始执行,极大的提高响应速度。如下序列图,分别指出了首次查询和以后分页的过程:
图一:首次查询序列
图二:以后分页序列
从图一可以看出,从于极多数的首次查询,由于都是取第一页数据,所以对于数据库网络IO和分页的时间,只占少数百分比。如果第一次查询,便是最后一页数据,则缓存分页所占的时间开销也不会参与计算。
l 设计接口
为了完成上述的序列逻辑,进行了比较繁复的代码设计。为了以后可以对类似的查询进行复用,数据层针对IDataReader接口进行设计,其它的操作封装在SearchResult类(负责从IDataReader取得记录并生成对象)和MemCachedResult类(负责缓存查询,分页,缓存结果集等操作),这里不再详述。
信息技术部 管理信息化中心 牛昆亮
二○一○年二月二十五日
附类图: