前段时间在使用ActiveMQ的时候遇到了一个比较奇怪的问题,最后被证明所有奇特的问题都是因为一些“奇特的做法”导致的。不过也很有意思,记下来了。
问题是这样的:我们在项目里使用ActiveMQ做为消息中间件,为了保证服务的高可靠,我们使用了多台MQ服务器,配置为主备模式,使用Oracle数据库提供消息持久化方案。
本来这是种很简单的部署模式,在测试环境也一切OK,偏偏在生产环境上线时遇到了问题,ActiveMQ打印了一行日志“no longer able to keep the exclusive lock so giving up being a master”后,就自动退出了。百思不得其解。
最后通过检查ActiveMQ的源码发现了该问题的原因:
原来,我们在生产环境上线时图省事,直接将测试环境里的ActiveMQ表导出建表语句,然后在生产环境执行,用来创建ActiveMQ需要用到的数据库表,恰恰是这一举动最后“弄巧成拙”了。
因为ActiveMQ本身提供了启动时自动建表的功能,它在建完表后还会自动插入一些初始数据,其中在ACTIVEMQ_LOCK表里的数据是用来模拟“锁”功能的,只有存在这行数据时,ActiveMQ才会通过修改这行数据来标识自己拿到了锁。相反,如果这行数据不存在,会导致ActiveMQ在试图获取“锁”(也就是试图修改这行数据)时失败,最终导致ActiveMQ退出。
知道了以上的问题所在,解决办法也自然就有了,就是把我们人工创建的那几个表统统删掉,然后配置成让ActiveMQ自动创建表,问题也就解决了。