首页 > 程序人生 > 技术的抉择
2018
03-26

技术的抉择

  几个月前我们决定从.NET转向Java的时候,我心里多少还是有些忐忑的,毕竟我已经好几年没碰过Java了。做了几年的C#开发,转到Java意味着工具集的整体替换。拿数据库访问来说,在C#里,我们用过EF和ADO.NET,追求开发效率用前者,追求运行效率用后者。到Java这,我的天,琳琅满目。一开始打算用Hibernate,毕竟大家都说这货就是Java里的EF,但担心有性能问题,所以只用它来生成表。EF里有个好东西叫数据库迁移,Code First,到Hibernate这就完蛋了,修改了实体字段,居然不能同步到表中。这对数据库的持续集成是致命的,搜索到了flyway,一用,什么玩意儿,弃之。后来同事写了一个工具类,从此再也不怕数据库的频繁修改了。至于数据库操作,搜索发现Mybatis呼声很高,好,那就它吧。技术团队就这么按部就班开干了。有一天我打开他们的代码一看,那叫一个头大。这么难用的玩意儿,同事们真是太实在了,居然没一个人抱怨。也难怪,压根没见过光明哪知道什么黑暗。后来我也加入到他们的开发,我们一起对JdbcTemplate做了一个封装,用的那叫一个溜,我甚至感觉似乎又回到了ADO.NET的快乐时光。类似的例子还有lombok,当我在那用快捷键生成getter和setter时,感觉跟吃苍蝇似的,就没什么工具么,一搜,果然,Google永远是人类的好朋友。

  无论在哪个行业,不跟风实在太难了,尤其像我这种Java半吊子,面临一些选择时更容易随波逐流,万能的安慰剂是:毕竟那么多人用,肯定有它的道理。但我觉得比追随主流更重要的是自己的感受,如果你自己都觉得恶心了,是不是该停一停,思考一下更优秀的替代方案,要知道世上那么多同行,都是人,有追求的人总是想用更优良的方式来解决问题,原创出最优解可能比较难,但搜索引擎至少可以帮我们找到它。关键就在于:不要摒弃自己的真实感受。难用就是难用,我在实践中确实没发现Mybatis比JdbcTemplate好在哪儿。另一个例子就是redis和消息队列。至今我仍然记得之前跟着一个所谓的大牛,眼见他兴致盎然地在项目中引入redis,没有IDE的前提下写着Lua脚本,美其名曰:可以利用redis单线程特性。这场redis灾难我记忆犹新,redis不仅没能帮我们解决性能问题,还引入了不必要的复杂性。当然,这不能完全怪redis,更主要的原因在于我们没有结合自身业务特点去正确使用,就一头扎入了redis大军中。不过,我至今都不觉得除了纯粹做为缓存以外redis还有什么其他更擅长的场景。还有消息队列,我觉得在一些非实时性项目中,用用mq还是可以的,可以达到所谓的削峰填谷的效果,不过就算不用mq,你用语言内置的本地Queue也能做到这一点,而且选择更多,比如ArrayBlockingQueue、Disruptor,还可以避免网络开销,更适用于实时性应用,部署时也不用再另外安装一个mq节点。

  话说回来,工具的出现都是为了解决痛点,所以如果时间允许的话,还是多尝试一下比较好,看看它是如何解决的、解决的质量如何,然后再综合考虑一下当前项目的实际情况,多做一些场景测试,再做决定。更何况有些工具的作者是有私心的,营销大于质量,弄不好解决的痛点远少于引入的痛点。

  最后说一下存储过程。我至今都反对使用这玩意儿,给运维部署带来麻烦不说,开发成本也高,而且带来的改善太少。数据库的本质工作还是应该在于存储数据,数据库的性能确实有限,拼了老命也只能榨出来一点,尤其是并发更新的时候,更要命,事务的隔离级别、行级锁这些控制好也只是解决了更新异常,性能问题依然还得想其他办法解决。所以如果实时和并发要求不高的话,没必要搞存储过程,要求高的话,存储过程也不能从根本上解决问题。数据库调优只能解决一些并发中等的需求。当然,这里所说的”不高“、”高“、”中等“,并没有确切的衡量指标,一切都得根据实际情况来。

  说到高并发的处理,之前我经常听到一个声音是:先写内存,然后异步写数据库,通过这样的方式来规避数据库瓶颈。但这里有个严重的问题:如果发生宕机,有些数据又没来得及持久化,那么这些数据就永远的丢失了,对于交易相关的业务来说,这是不能接受的。想象一下:客户已经得到了充值成功的提示,结果服务器挂了,重启后,客户再一看页面上,钱没了。结合最近的学习研究,对于高并发处理,我倾向的观点是:

  • 将持久化的代价降到最低(比如实时的持久化不用数据库,而是使用RandomAccessFile,这货的性能真是超乎想象),中心服务器完全运行在内存中,所有的业务逻辑都没有数据库操作、远程调用。
  • 避免多线程竞争和伪共享问题,单线程的处理能力其实是非常高效的,这方面的一个典型例子就是LMAX公司,有兴趣的可以搜索一下,他们在多年前就达到了600万TPS的惊人处理速度。

  当然,以上都是学习研究,至于具体如何,还有待我们在新的项目中去实践出来。不管怎样,取舍的关键永远在于:用最低的成本来解决实际问题,这个成本包括时间、精力、金钱等等,这是宇宙第一原则。

编程技巧