DAL 又更新了

2010年07月22日

经过一个月的忙碌,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 的介绍可以看超前同学的博客。在这段开发过程中接触了很多开源软件,也浏览过一些源代码,个人认为 php 和 mysql 的源代码质量比较一般,如果打算读开源代码不建议选这两个。

DAL 最近的一些进展

2010年06月20日

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

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

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

国立中央大学

南京大学

今年的 QCon 大会

2010年04月25日

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

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

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

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

2010年04月25日

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

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

最近工作的一些思考

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

来到新部门一个多月了,新的部门目前的工作重点是研发一套分布式数据访问系统。开发团队由三位成员组成,各自负责一部分组件的研发。

这一个多月来,代码写了不少,错误也犯了不少,时间也浪费了不少。今天做一些总结,以免日后遗忘。

  • 设计要自由、大胆,最后落到实处
    做设计尤其是做新的系统设计,不要拘泥于已知的东西,要大胆的设想,否则就是原地踏步,设计出来的东西没什么创新,亮点很少,客户当然不会买账。做完设计后要想想,哪些可以做,哪些比较难做,分清主次和先后,逐步实施。不是说设计好了就要一次性做出来,任何伟大的系统都是一砖一瓦搭建起来的。
  • 对系统抽象后,系统结构应该非常清晰
    系统中结构不清晰的部分往往是没有考虑周到的部分,如果短时间内考虑不好,不如暂时放下不要急于动手。或者试着做一点,新的、好的想法说不定就显露出来了。
  • 动手写代码之前基本的逻辑是要清晰的
    经验不丰富或者是涉足新的领域,一般很难事先把所有的逻辑都考虑的清清楚楚,但是至少大体上是清晰的。如果对系统没有一个大概的想法,急于动手去做,结果往往是很悲惨的。
  • 写代码过程要心细严格
    整个系统的开发过程中,设计和调试用的时间比较多,减少这两块时间就提高了效率。“敏捷开发”的思想就是不要像传统软件开发那样做过多详细的设计,大概想的差不多就着手开发,一边开发一边修正设计,这样设计的时间就减少了。如何减少调试时间呢?往往需要花时间调试的代码都是写的时候不仔细,犯了一些很低级的错误,但是却浪费了大量的调试时间,所以写代码的时候还是尽量细心严格。

鄙视养狗不拴狗链子的

2010年01月19日

如题。

一年又过去了

2009年12月31日

首先祝大家新年快乐!

转眼一年又要过去了,我给自己 2009 年打 70 分。在工作上我还比较认真,我觉得老板给了你一份工作,要不就认真做,要不就走人。09 年在读书学习这方面做的不好,先后也买了一些书,但是完整看完的很少,以后要杜绝浮躁,静心花些时间来读书。08 年最后一天领结婚证了,但是我觉得这一年还没有很好的尽到一个做丈夫的责任,没有多花点时间陪老婆,以后也要好好改进。自从 07 年工作以来,身体持续发福,后面不一定有很多时间来锻炼,但是一定要控制饮食。

时不待我,我不待时。

MySQL 的 master-slave 复制实施细节

2009年12月19日

很多 WEB 站点使用 MySQL 的 master-slave 结构,写请求都在 master 数据库上操作,读请求都在 slave 数据库上操作,这样就减轻了单台数据库的读写压力。MySQL 是如何实现数据从 master 到 slave 的同步呢?

当 slave 发起了 START SLAVE 指令时,slave 会创建一个线程来连接 master,让 master 发送二进制的更新日志。当然这里有两点要明确的:1)master 必须记录二进制更新日志;2)slave 必须告知 master 要从哪个点开始复制二进制日志。master 收到 slave 的请求后,也会创建一个线程,从指定的点开始给 slave 发送二进制日志。slave 会有另外一个线程根据接收到的二进制日志来更新本地数据。这样就实现了 master 到 slave 之间的数据同步。

PHP APC 到底有多快

2009年12月19日

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 加速后,效果还是很可观的。

大规模并行计算简介

2009年11月29日

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

为什么 GPU 适合做大规模并行计算?
GPU 当初设计就是用来做图形处理的,而图形处理本身就是高密度,高并行的计算.请看下图:

a

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

CUDA 是什么?
简单来说 CUDA 就是通用的并行计算架构.包括硬件指令集和并行编程模型.请看下图:

b

目前应用程序可以通过 C 语言来使用 CUDA 架构,从而解决很多复杂的计算问题.其他的诸如 FORTRAN,C++,OpenGL 和 DirectX 等语言或者编程接口会陆续支持.

如何在 CUDA 的编程模型上开发并行运行的程序?
CUDA 编程模型扩展了 C 语言,可以使用扩展语法调用 C 语言定义的特殊函数(这种特殊函数称作 kernel).请看下面的代码:

当用 CUDA 扩展语法调用 kernel 时,kernel 会被 N 个不同的线程同时执行.

CUDA 的硬件是如何实现的?
简单来说当 kernel 被调用时,GPU 会自动分配线程到各个 GPU 计算单元去执行并处理线程的共享资源.因为 GPU 拥有大量的计算单元,当大量的线程在各自的计算单元上运行时,偶尔的共享资源访问延时也可以忽略了.

更多详细信息可以查看 NVIDIA 公司的站点.