司马刘的日志

分享工作,分享生活。

Skip to: Content | Sidebar | Footer

Category: 开发

DAL 又更新了

22 七月, 2010 (19:57) | 开发 | By: 司马 刘

经过一个月的忙碌,DAL 又更新了,内部版本号为 2.3.5。这个版本主要改进以下几点:
协议改进。之前版本的 DAL 使用 php 序列化作为数据传输协议,这是一个历史遗留的问题,因为最早的 DAL 是完全用 php 实现的。现在仔细考虑过后认为 php 序列化肯定不是好的编码格式,首先 php 序列化是文本格式的,并不高效;还有很致命的一点就是 php 对数据类型支持很差。比如:php 不支持 double 类型,如果打算用 java 语言实现一个 DAL 客户端,那么这里无疑是丢失了数据类型信息,所以 php 序列化肯定是不够用的。新的编码格式目标就是高效,并且对数据类型有良好支持。参考了 mysql 数据库协议和 igbinary 序列化格式,最终考虑采用二进制协议。如何支持数据库的多种数据类型呢?我们是这么做的,server 端返回的查询数据是一个表格,表格有表头和表内容,我们在传输表头时就传输了每列的列名和列类型,这里列类型和 JDBC 的数据类型是一致的,表内容全部采用字符串编码,这样可能会多传输一些字节,但是避免了精度问题,因为数字也是用字符串编码的,当然没有精度问题。这样的好处是 DAL 不同的客户端可以根据各自语言特点来解码。协议设计好后先用 php 实现了一个版本的解码器,由于 php 本身性能问题导致 php 版的解码器效率比较低。接下来又用 php 扩展实现了解码器,性能有大幅度提高。在大数据解码方面比 php 序列化快几十倍,比 igbinary 快一点点。
对数据库函数的处理。DAL 需要操作缓存,需要考虑数据库切分,所以不得不分析用户的查询请求。如果用户使用了数据库函数,这个分析就变的异常困难,因为你不知道(很难知道)用户调用的函数中使用了什么函数,涉及到哪些字段。目前的临时解决办法是:只要用户使用了数据库函数,用户就必须显示的指定是否缓存;如果用户这个请求需要辅助表完成,那么 DAL 会强制选择第一个辅助表而不进行任何优化选择(关于辅助表选择优化请看《DAL 最近的一些进展》)。
数据库条目缓存结构调整。以前数据库条目缓存包含了条目的属性和数据两部分信息。很显然,没必要缓存条目的属性,因为条目属性在系统启动时就可以加载,在整个系统运行期间不会改变,没必要每次写到缓存里。缓存数据库条目时所有字段都是按字符串格式存储的,这样做无疑增加了缓存条目的体积,但换来的是保证不会在 server 端丢失数据精度,同时数据格式和协议是一致的,便于操作。
大体就是这些改进,关于 DAL 的介绍可以看超前同学的博客。在这段开发过程中接触了很多开源软件,也浏览过一些源代码,个人认为 [...]

DAL 最近的一些进展

20 六月, 2010 (11:10) | 开发 | By: 司马 刘

上个月我这个部门走了两个人,我的意思是说现在我这个部门只有一个人。DAL 的研发工作目前是由我一个人负责。一个人做事的弊端就是想法比较局限,代码写了只有自己觉得好不好,也没有别人来评价。不管怎么说,DAL 还是在稳步前进。下面就说说 DAL 目前的一些进展。

选择最优的索引表完成查询。数据分片后为了便于排序和做一些聚合操作,每套分片都建了若干个索引表,有查询请求需要索引表辅助完成的时候,以前是随机选一个可用的索引表,现在引入了一个评分的算法,给每个索引表评分,选得分高的索引表。评分的依据主要是索引的使用情况,大体来说就是有索引比没有索引好,联合索引比单个索引好。目前这个特性在手机之家测试机上运行良好,情绪稳定。
对并发查询请求的优化。在生产机的数据库上经常会看到有同样的 SQL 请求在数据库中执行,DAL 能不能为这种情况做些优化呢?我们想到了这样的办法:每次执行数据库查询的时候记录一个请求执行上下文,当有同样的请求并发到达时,只有严格的第一个到达的请求会查询数据库并将查询结果保存在执行上下文中,其他请求都等待第一个请求完成,然后直接使用上下文中保存的查询结果。当然如果对某个表有更新操作,这个表的所有执行上下文都将被删除,保证数据的一致性。还有如果查询中包含时间函数也不能使用这种优化机制。
编码优化。以前的 DAL 使用 php 序列化编码结构化数据。其实只要稍微想想就知道这肯定是个不好的方式,但是由于历史原因,这种编码方式一直持续到现在。php 反序列化大数据时性能相当差,并且 php 只支持少数几种数据类型,用 php 序列化编码的数据无法跨语言使用。新的编码主要要解决性能问题和数据类型跨语言的问题。这部分工作目前还在进行中,以后会给出结果。

大概就是这些,最后再附几张大学校门图,这也能看出国家正在进步嘛!

今年的 QCon 大会

25 四月, 2010 (21:37) | 开发 | By: 司马 刘

这个月的 23、24、25 三天参加了今年的 QCon 大会,总体来说感觉比较失望。尤其是国内部分公司的演讲。从这几家公司的演讲可以看出公司很浮躁(当然,我自己也比较浮躁),这也是 IT 业界乃至国内的常态。大体有这几方面的现象:

公司初期,没找到盈利模式,不断做一些尝试,这个很正常;而很多有一定规模的公司还是没有自己的目标和原则,WEB 2.0 来了,大家都说自己的站点是 WEB 2.0,国外公司推出个啥啥啥,国内公司纷纷效仿也做个啥啥啥。
技术人员急于转管理,公司技术根基不扎实。我认为任何一个公司没有一支强大的技术团队都是很难成长的,但是看国内大部分公司并没有很重视技术团队,技术管理人员对技术知晓甚少。
国内开源社区一直很冷淡,很多公司在大会中提出要开源自己公司开发的啥啥啥,试问,这些软件开源后有多少人会研究,有多少公司敢用,这样的开源对社区有多大意义?我还是比较佩服一些公司默默的为熟知开源软件提供 patch。

最后感谢国家,感谢老大给我这个大会名额。

最近工作的一些思考(续)

25 四月, 2010 (20:47) | 开发, 默认分类 | By: 司马 刘

前面写过一篇 最近工作的一些思考 ,现在有过了一个多月,又有了一些想法,继续做一些记录。

仔细审视你的设计
设计不好的系统不仅是不好维护,更是滋生 bug 的温床。

不要为不成熟的系统做过多的优化
《UNIX 编程艺术》中的优化原则是:雕琢前先要有原型,跑之前先学会走。 显然不成熟的系统,代码变动频繁,今天做的优化明天可能因为设计问题又要改掉。比如,在开发 dal 过程中,为了少获取数据库连接,尽量取一次连接,反复使用,结果引入分布式事务后,这样的代码不得不改掉。
工作任务合理安排
长期的工作目标肯定是要明确的。第二天要做什么,做到什么程度,遇到问题卡住了怎么办,这些最好提前想清楚了,这样每天工作效率高,也觉得很有成就感。工作任务一定要明确记录,比如:“完成配置文件解析”,而不是“看代码,改 bug”。
代码一定要严格对待
申请的资源不用了一定要释放,该判断的逻辑一定要判断,而不是说“一般情况下,这段代码没问题,如果怎么怎么,代码可能不行”。保证在任何时候任何可能发生的事情都要在掌控之中。
选择第三方开发包时要慎重
使用前一定要仔细看文档,做好测试工作,也可以上网搜一下大家对这个开发包的评价。否则,用了一段时间发现有各种各样的问题必定很郁闷。

最近工作的一些思考

9 二月, 2010 (20:49) | 开发 | By: 司马 刘

设计要自由、大胆,最后落到实处来到新部门一个多月了,新的部门目前的工作重点是研发一套分布式数据访问系统。开发团队由三位成员组成,各自负责一部分组件的研发。
这一个多月来,代码写了不少,错误也犯了不少,时间也浪费了不少。今天做一些总结,以免日后遗忘。
来到新部门一个多月了,新的部门目前的工作重点是研发一套分布式数据访问系统。开发团队由三位成员组成,各自负责一部分组件的研发。
这一个多月来,代码写了不少,错误也犯了不少,时间也浪费了不少。今天做一些总结,以免日后遗忘。

设计要自由、大胆,最后落到实处
做设计尤其是做新的系统设计,不要拘泥于已知的东西,要大胆的设想,否则就是原地踏步,设计出来的东西没什么创新,亮点很少,客户当然不会买账。做完设计后要想想,哪些可以做,哪些比较难做,分清主次和先后,逐步实施。不是说设计好了就要一次性做出来,任何伟大的系统都是一砖一瓦搭建起来的。

对系统抽象后,系统结构应该非常清晰
系统中结构不清晰的部分往往是没有考虑周到的部分,如果短时间内考虑不好,不如暂时放下不要急于动手。或者试着做一点,新的、好的想法说不定就显露出来了。

动手写代码之前基本的逻辑是要清晰的
经验不丰富或者是涉足新的领域,一般很难事先把所有的逻辑都考虑的清清楚楚,但是至少大体上是清晰的。如果对系统没有一个大概的想法,急于动手去做,结果往往是很悲惨的。

写代码过程要心细严格
整个系统的开发过程中,设计和调试用的时间比较多,减少这两块时间就提高了效率。“敏捷开发”的思想就是不要像传统软件开发那样做过多详细的设计,大概想的差不多就着手开发,一边开发一边修正设计,这样设计的时间就减少了。如何减少调试时间呢?往往需要花时间调试的代码都是写的时候不仔细,犯了一些很低级的错误,但是却浪费了大量的调试时间,所以写代码的时候还是尽量细心严格。

PHP APC 到底有多快

19 十二月, 2009 (18:33) | 开发 | By: 司马 刘

APC(Alternative PHP Cache)是一个免费开放的 PHP 代码缓存模块。很多 WEB 站点都使用 APC 来加速,APC 的效果到底如何呢?笔者作了如下实验。
两个 PHP 文件,内容分别为:

开启 APC 模块和禁用 APC 模块,分别执行 b.php 文件,结果如下:
[root@localhost ~]# time php b.php
real    0m0.059s
user    0m0.031s
sys     0m0.019s
[root@localhost ~]# time php b.php
real    0m0.123s
user    0m0.036s
sys     0m0.069s
从上面的数据可以看出使用 APC 加速后,效果还是很可观的。

大规模并行计算简介

29 十一月, 2009 (18:35) | 开发, 杂项 | By: 司马 刘

当今信息化时代,计算机需要处理的信息量呈几何级数增加,但是由于 CPU 架构本身的局限,CPU 时钟频率提升已经遇到了瓶颈.而最初只作为图形处理的 GPU 的可编程性日益增加使得很多科学家开始使用 GPU 来运行通用的计算程序.今天我给大家简单介绍一下 GPU 以及 CUDA 架构.
为什么 GPU 适合做大规模并行计算?
GPU 当初设计就是用来做图形处理的,而图形处理本身就是高密度,高并行的计算.请看下图:

GPU 的计算单元非常密集,可以让多个线程在多个不同的计算单元上同时运行,而 CPU 上的进程切换是一个很耗资源的操作,进程内的多个线程共享一份内存和寄存器,CPU 上的多线程并行和 GPU 的多线程并行性能必定有很大的差距.但是 CPU 的复杂的指令流控制是 GPU 的弱项.所以目前大多采用若干个 CPU 和若干个 GPU 来构建大规模并行计算系统,应用程序的顺序部分在 CPU 上运行,计算密集型部分在 GPU 上运行.
CUDA 是什么?
简单来说 CUDA 就是通用的并行计算架构.包括硬件指令集和并行编程模型.请看下图:

目前应用程序可以通过 C 语言来使用 CUDA 架构,从而解决很多复杂的计算问题.其他的诸如 FORTRAN,C++,OpenGL 和 DirectX 等语言或者编程接口会陆续支持.
如何在 CUDA 的编程模型上开发并行运行的程序?
CUDA 编程模型扩展了 C 语言,可以使用扩展语法调用 C 语言定义的特殊函数(这种特殊函数称作 kernel).请看下面的代码:

当用 CUDA 扩展语法调用 kernel [...]

MySQL 优化总结

24 十一月, 2009 (20:18) | 开发 | By: 司马 刘

有很多人都问过我如何优化 MySQL,苦于自己一直没有好好总结,总是不能有条理的讲出来,今天就来总结一下.
安装和配置
如果没有充分的理由请不要自己动手编译 MySQL,官网上提供的编译好的包就够用了, MySQL 文档中提出用 ICC 编译的 MySQL 性能要优于用 GCC 编译的.如果你的服务器是 Intel 架构,请下载用 ICC 编译的包.安装好了肯定是要做一些配置的,我通常都是用 MyISAM 表引擎的,所以只总结关于 MyISAM 的配置优化.MyISAM 主要有以下参数需要注意:

query_cache,开启 query_cache,MySQL 会缓存 SELECT 查询语句和查询结果,当遇到相同的查询语句时不用解析查询语句而直接返回查询结果.query_cache 在互联网应用中有不错的表现.
key_buffer_size,这个选项指定索引的缓冲区大小,适当增加这个选项的值会得到更好的索引处理性能.
sort_buffer_size,这个选项指定用于排序的缓冲区大小,适当增加这个选项可以提高 ORDER BY 和 GROUP BY 的效率.
read_buffer_size,这个选项指定扫描表时的缓冲区大小.

最后别忘记开启慢查询日志和没有使用索引的查询日志,这些日志在改善查询性能非常重要.
设计数据库/表
这绝对是个相当重要的环节,在开发过程中发现数据库设计不合理再返工绝对是要命的.MySQL 非常善于处理数字类型字段和固定长度类型字段,单表记录大于千万时性能表现不佳.所以我们设计数据库时最好遵循下面几条原则:

主键/ 唯一键/ORDER BY 字段/GROUP BY 字段使用数字类型字段
除非有必要,否则数字类型字段请用无符号数字类型
除非有必要,否则字符串类型字段请用 latin1_bin 编码方式
权衡选择固定长度类型和可变长度类型
预估一个表的记录数和字段数目,如有必要请横向/纵向拆分表
不要给字段设置 NULL 值
建立必要的索引

设计 SQL
很多开发人员觉得能写出很复杂,很酷的 SQL 是一件值得骄傲的事情,这里我要说的是”醒悟吧,孩子”.尽量用最简单的 SQL 来完成任务,如果你的 SQL 不能写的简单,那说明你的数据库设计的不合理.设计 SQL 也有一些原则:

SQL 只查询需要的记录的行/列
不要在列上作计算,数据库不是做计算用的,请在程序里想办法
尽量不要用 GROUP BY 和 JOIN
查询尽量能用到索引

在生产环境中观察
项目上线了,真正的烦恼才刚刚开始.MySQL 既然记录了日志,就经常看看,看看哪些 [...]

手机之家站内搜索改进

11 十一月, 2009 (22:23) | 开发 | By: 司马 刘

刚接到手机之家站内搜索 (项目名: batu, 基于 lucene 的站内搜索系统) 的时候真是有几天几夜没睡好,原因是这样的:
1) 有几位前人 hack 过这个项目的代码,代码结构和风格有很大差异;
2) 有部分逻辑是用 bash 脚本实现的,虽然是短短的 200 多行脚本,读起来真是很晦涩;
3) bash 脚本太多,部署非常麻烦;
4) 没有文档,小公司从来都是这样的.
代码大体浏览过一遍,开始定一个目标,大概是这样的:
1) 变量,函数命名标准化;
2) 减少脚本数量使部署更简单;
3) 各个子系统直接采用 socket 通信,而不是目前的写 FLAG 文件的方式;
4) 去掉 lucene 的 QueryParser,用各种子 Query  组装目标 Query;
5) 升级到最新版的 java NIO 框架 — monkey ;
目标定下来就开始写代码,除了一些工具类,其他代码基本都重写了,历时近两月.上周在生产机上部署 batu,没发现大的问题.新的 batu 优点如下:
1) 代码结构更清晰,变量名,方法名,文件名等更加规范,代码也更容易阅读和维护;
2)每台机器只要执行一个脚本就完成了部署工作,大大减轻了运维工作;
3)各个子系统采用 socket 通信,方便把各个子系统部署在不同机器,也降低了子系统直接的耦合;
在这两个月的开发过程中总结出来几点经验和大家分享:
1) 记详细的日志(log4j),便于跟踪代码的执行流程;
2) 做好自动化测试工具(脚本),代码改过后跑一下脚本看看日志就知道大概的情况了;
3) 制定小目标,逐步迭代,避免长时间闷头开发失去目标;
4) 遇到难题时主动向高人请教,别人稍微一指点或许你就茅舍顿开;
接手别人的代码真是”如人喝汤,冷热自知”啊.