转载请注明出处(http://www.cnblogs.com/goldentime,作者:黄金年代。文章虽差也属原创,苍蝇虽小也是块肉!)
被网上小将们骂怕了。但是该写还是要写,而且坚持原创继续毁人不倦。我们的口号是(没有蛀牙!!!)
本垃圾文章描述了一种类似于缓存的查询方式,将数据放入内存中进行查询,从而达到提高响应速度增加吞吐量的目的。方法简单,属于原创。缺点等待大家来评论。
本文技术内容其实很简单,但是我前边会写一些技术之外的东西,因为不仅在中国就是在世界上很多东西比技术更重要。毕竟技术是为了更好的提供服务。往往是最末的一环,请各位程序员和准程序员清醒这一点。另外还简单介绍了设计的过程欢迎有同样小型项目管理经验的同道评论,也给初学者参考。
正文开始:
之前我们参考了南方兄弟招办已有系统(运行过一年,我们本来想去年搞,但是没搞起来,人家先做了)地运行情况。算是学习了经验。最后我们认为整个系统的压力应当集中在填报志愿过程中(废话)。
填报方案选型过程:
一、如果考生直接选择院校名称和专业的话,对服务器和网络压力太大,该方案淘汰。(在后期征集志愿时由于院校数目少可以考虑)
二、志愿翻译:简单说来就是:考生输入报考院校的学校代号和专业代号,然后系统翻译为现实的名称,考生检查是否正确即可。
例如10003:01,02 翻译为:清华大学:工程力学与航天航空工程,艺术设计学。
选择:方案二,考生填写代码,系统翻译志愿。
设计实现过程
设计目标:
翻译过程很简单但是主要是次数比较多。每位考生一次填写正确需要翻译9批次*2-5院校*1院校名称+6专业名称=250次左右的翻译。共55万考生。一共需要翻译1.25亿次。平均到2天的工作时间16小时,平均每秒翻译2170次。再用正态分布估算。我们觉得每秒1万次翻译作为设计目标应当能够满足实际应用的情况。
说起来简单,实际上每个学校翻译的时候还需要判断科类、考生类别、限报条件等,所以sql查询语句效率不会太高。
翻译方案选型:
一、Sql存储过程
已有系统的查询使用存储过程来完成查询,将web服务器和数据库服务器之间的通信减到最小。然后通过对数据库进行优化将性能最大化。
这种方法比较成熟,也是大家首先能够想到的,实施起来风险也较小,数据流量也可很容易的分布到多个数据库上(不要给我提什么群集,挖掘一类的,我们有2台F5,根本不需要那么麻烦再烂的系统也能够运行的差不多。但是不能那样做事。第一设备再先进,也要你的底层架构设计合理才可以。第二、设备技术再先进是人家微软、IBM的又不是自己的,要想进步,要自己去努力。我实在不明白为什么有些人使用起那些名词来那么理直气壮好像是自己发明的一般。)
为了规避风险我们首先实现了该方法,但是并没有在数据优化时下功夫因为我们认为,这种方法效率不高。比如:我们仅仅是只读的查询。一共的3万记录进行1.25亿次查询相当于每条平均查重复4000多次,这是巨大的性能浪费。
而且sql查询时作负载均衡我们嫌麻烦,我们这时就是想要试验去做一种没有试过的高效的内存查询算法。看看到底能要出多少性能来
二、专有数据库查询:实际上无论是平易近人的mssql还是走下神坛的ORCAL由于太大,求全涉及到方方面面。他的数据查询效率并不如专有数据库效率高。就像CE不如PALM快,虽然PALM不先进但是运行快。但是时间长了,由于CE的通用性和兼容性还是占据了比较大的市场。
但是专有的数据库用起来一方面技术比较冷门,另外我们没有时间去进行评估也就无法去选择。单独为一个系统去学习一个冷门数据库不划算。
三、内存数据库,目前内存数据库上网查了查有一个韩国的厂商在工控领域做的不错。另外好像微软的Microsoft SQL Server 2005 Compact Edition
(这个不确认是内存的,但是好像支持,而且好像对多用户支持不好或不支持)做的也不错。感兴趣的去这个地址:http://www.microsoft.com/downloads/details.aspx?FamilyId=E6BC81E8-175B-46EA-86A0-C9DACAA84C85&displaylang=en#filelist
四、私有算法。我们最后选择了自动开发一种查询算法。因为:
1、 创新的需求。做东西技术人员总要有所追求创新,有个东西是你自己的,总是用别人的有啥意思?
2、 我们的查询比较简单,没有必要实现到数据库的层次。为了我们简单的查询,没有必要去实现Codd十二法则?这样我们就可以借着这个项目研究新技术,同时还可以控制风险。
3、 时间充裕:我们设计完之后,用2天就实现了基于内存查询的并进行了评估(虽然网上没有现成的,但是只要想到了确实很简单,就和原来我们写汉字字库实际上一样),结论是值得一试。
具体实现:(请注意本文的实现与现实严格关联,因为实际工作中这些政策年年变,不可能复用,所以也就没有完全面向对象,而只是抽了出来做成类方便维护而已。)
系统具体实现部分
系统实现的原理:
原理很简单将数据放入数组或哈希表中,然后查找即可,关键是如何实现。
关键在于:
第一、 如何将表放入内存中。
第二、 如何对外提供查询。
对于第一个问题我们可以很简单的通过将数组和哈希定义为静态变量从而常驻内存。
请原谅我的代码中有拼音因为。。。教育部的表就是拼音缩写的,因为广大招办有很多老同志,都换成英文不可能。
然后在构造函数中填充数据例如:
对于第二个问题,就好说多了,有了数据,查询、就是了。。
好了不说废话,看程序。。
系统代码实现:
调用方式说明:传入的为一个ARRAYLIST 00001,01,02。。。。
终于完了,能够看到这里的都是高手(没有耐心成不了高手)。其实给出这么长的代码段并没有必要,但是如果修改太多又需要时间太多,而且其中有一个修改的地方能够很好的诠释一些不在计划中的意外的处理。所以就直接搬上来了。
原理很简单,实现也不麻烦。
实际效果很好,能够实现每秒百万次级别的查询。而且仅仅加载时访问数据库。我想这可能是这种特殊环境下的最高效率了。
原因很简单:
第一、翻译院校名称根本就没有查找过程,直接下标访问的。
第二、翻译专业名称时哈希表的算法复杂度与直接下标访问差不多(多一次计算hash值)
希望有人能够告诉我有没有更好更快得方法。我很感兴趣。
我这里有负载评测本方法与数据库查询方法比较的测试数据(不使用存储过程的未经优化的数据库同样查询每秒300-1000次,性能保守快2个数量级以上。),改天整理一下再放上来。
反思:
1、 实现的缺陷,静态方法支持多线程吗?我不大好说,但是负载测试时确实4个cpu都跑起来了。盼望高人指点。
2、 该方法占用内存。我们加载了全部3万条记录后,大概占用60m左右内存。当然对于现在我们动辄4g以上的内存不算什么。
3、 不支持sql标准查询。
4、 如果海量数据,内存盛不下如何操作?还有如何支持数据更新?我目前没事的时候在研究这个。希望在用户和数据库中增加一个中间层作缓冲,从而进一步提高数据库吞吐量。作为高考数据量可能没有这个必要,但是对性能的需求是无止境的。
5、 该方法使用起来可靠吗?实际使用时没有出现问题,不知道有没有高手指出可靠性的缺陷。
6、有没有人能够比较与.net新增的缓存的比较。