多路数据库连接

多路数据库连接的需求来源是这样的,我们的管理后台和游戏服务器分居两台机器,大多数时候的查询操作是在后台本地,但涉及到赠送物品时需要访问游戏服务上的数据库。之所以会搞两台服务器是需要统计游戏服务器产生的数据,若都在一台服务器上运行势必会造成磁盘、内存不够用,遂将游戏服务器上的数据同步至管理后台进行统计。之前我们的解决方案是在游戏服务器上只启动能够赠送物品的服务,并在管理后台服务器上启动其余的服务器。这样对于数据库连接管理来说是相对简单的,不用在操作过程中进行切换。后来我觉得有一种更为好的方案,就是在每一个操作中区分好需不需要写入到游戏服务器数据库,若需要便切换过去,并且在使用完之后切换回来,可以在一次请求中切换多次。例如,我们在每次操作时都是需要记录操作日志的,而操作有可能是针对游戏服务器的,所以这一次请求中就有了两次切换。我称这个为多路数据库连接。

实现的方式很简单,我们配置了两个数据库连接池,一个指向本地的,一个指向游戏服务器的,并将他们配置到哈希表中。将当前所选择的数据库连接记录在线程本地变量中,切换就是更改线程本地变量记录不同的连接池的键。同时,为了满足在一次操作中可以切回原来的数据库连接,此处实现了一个切换帮助对象,当切换时此对象内部可以记住原来的连接键,并在完成操作之后调用重设方法切换回原来的连接选择。如此完成在一次请求中多次切换。另外我们还实现了自己的事务管理,即封装自己的连接并将配置的连接池的所有在事务中获取的连接都放到一个表中,当最终提交时将所有的连接中的 Statement 提交,而如果中途任何地方调用了连接本身的提交是不会真的提交的。整个方案的构思并不难。

在实现过程中我遇到了 jar 没有源码却需要修改其中逻辑的需求。这个也不难,使用一个反编译工具将 class 文件反编译出来,然后用 javac 在编译成 class 文件,最后用 jar 将其打包成一个完整的 jar。不过反编译工具也遇到一些小问题,比如明明方法需要返回 String 类型,可以某个 return 语句会返回 Long.parseLong(..) 这样的返回值。这个问题没有深究,所以没有经过长时间检验的东西最好是抱着随时填补错误的心态会比较容易一点。

顺便谈一下 Scala 这门语言,之前由于 Scala 的 Actor 并发模型以及函数式编程一直很吸引我。我也花了好几天的时间看<Scala 编程>这本书,发现了一些问题,就是 Scala 的语法实在是太多了,而且使用了大量的操作符,给我的记忆和理解带来了很大的阻碍。毕竟 Scala 想要兼容函数式和面向对象编程两种不同的范式。除此之外我还觉得 Scala 的解释器和 Intellij IDEA 的 Scala 插件运行起来够慢的。简单的编译工作也花费了不少时间等待。随即我的想法是像 Scala 这些小众的语言,使用的人数不够多,需要要优化的地方却未得到优化,许多隐藏的 bug 也未得到修正,这些都是使用小众语言所必须冒的风险。我可能不会使用 Scala 进行正式的开发,但多了解一门新的语言也算有所受益,并且学习 Scala 也是我一直以来的心愿,难得最近花了时间去学它。

Leave a Reply

Your email address will not be published. Required fields are marked *