春节接近,团队小伙伴们作业的斗志正在逐渐松散,期待这时光快些吧,早发年终,安安心心过个年,认为这几天就能安安稳稳度过了,但直到x日x团队x同学传来捷报:你们提供的敏感数据审阅功能出现问题了,使命现已履行了几个小时了,都没处理完,赶紧看看是怎样回事吧。

听了这话,我是又惊又怕,项目从属的集团属于国企,对用户的各种数据安全管控十分高,日常用户发布的数据有专门的审阅团队在担任,但跟着 吴签等很多艺人沦亡,需求对涉及到的各项数据完结动态下线,全体是由体系运营部门建议下线使命,咱们这面依据需求处理并上报成果,然后他们再依据成果来决议哪些需求真正下线。流程便是这么个流程:

记一次D腾的现网数据库问题排查经历,真相是万万没想到!!

No,这绝对不可能是我这面的问题,我自傲满满,由于这个服务是去年7月份投入了近半个月时刻从需求对接到开发测试再到上线,虽然要匹配几千万的数据,功能不说快,但全体试根本能在20分钟左右完结匹配和成果数据生成,但他们说的也是现实,仍是开端定位问题吧。

前两天咱们这面服务上过线,先排查一下是不是其他同学代码改动影响到了,尤其是涉及到数据库装备方面的,由于这种事情说不好,有时分开发影响规模没评价好,一些改动可能会把看似无关的功能给毙了,仔细核查了代码,发现根本便是事务性质的代码改变,那事务应该能够排出了。 突然想到还有一个可能,是不是运维他们晋级tomcat发动账号导致的(集团要求,这个是根据传统tomcat的war项目,需求改成非root发动),莫非是这个影响到了?由于他们改了tomcat发动账号后,导致一些事务涉及到临时目录没权限而导致事务反常了,遂找运维承认,运维立马给出了否定:咱们这个账号安全晋级,是不会影响到事务体系读取数据库的,这些都是根据内网的服务衔接,能够根本忽略网络开销。
:是不是可能是数据库的问题?
运维:不可能,数据库有问题早就告警了,你仍是先从事务上考虑问题出在那儿吧。

难了,事务上未做改动,数据库没问题,这咋定位呢,那就把日志打详细点,看每步的功能耗费,发布调查,单次数据库查询耗时超越100s了,乃至慢的时分将近200s,事务处理部分很快10-50ms,这什么状况?

记一次D腾的现网数据库问题排查经历,真相是万万没想到!!

:杰哥,这个数据库查询怎样耗时这么多啊,事务这块没改动过啊,是不是数据库有什么问题或者是数据库做了什么装备上的改变?
运维:不会,数据库同事那面有操作会给咱们说的,你把查询句子给我一下,我履行一下。
所以按事务查询逻辑拼接了查询脚本给到运维。

记一次D腾的现网数据库问题排查经历,真相是万万没想到!!

运维:很快啊,根本是ms级,主从库都查询了一下,都很快。

我不禁对自我发生了怀疑,莫非事务的服务版本太旧了?抱着试一试的心态,我把事务代码迁移到一个SpringBoot项目中,验证单轮数据读取100-500ms,事务处理部分不超越50ms,这个数据就康复了之前的状况了,乃至还要快一点。
:杰哥,这个我用war很慢,jar就很快,这个感觉是数据库的问题吧,毕竟这块的事务没变动过啊(解释不清这现象)。
运维:那你只装备xxx.62这个IP呢,这个是物理节点,其它两个是虚拟机的。

遂再验证,果然仍是绝望了,war的功能根本没任何改变。 不禁又怀疑是tomcat发动账号问题了,后边运维切换回root账号测试了,相同!跟着时刻一点一点消逝,我有点焦急了,现已找不到办法了,只要向老迈请教了。

咱们一起先看了数据库,在三台服务器上别离履行这个查询脚本和运维的测试成果相同,是很快的,然后在Studio 3T(Mongo客户端)上翻页,有差异了,主库的翻页很慢,两个从库的很快,这就感觉有点玄学了(这块就只要数据库同学去定位了),不禁发生一丝敬意。 然后让我这面把主库的IP去掉,只留两个从库的IP呢,你认为这样就行?仍是仍是相同。

然后又轮流从多个角度进行测试!!!

idea result
1. 操作小数调集,单次1W条 100+s
2. 每次读取5000条 80s附近浮动
3. 每次读取1000条 10~20s
4. 不要条件操作一个小调集,单次1W条 100+s
5. 运用阿里arthas剖析 测试一半有其它事情中断了
…… ……

我向老迈提主张:真实定位不到,就切换到根据SpringBoot项目里面去吧,可能是war服务的组件问题(有些东西便是玄学不好解释)。老迈也同意了,咱们仍是在deadline前再剖析一下吧

持续探索吧,天主不会孤负一个有决心的人! ….. 好像忽略了一个问题,SpringBoot项目的Mongo衔接装备是读写别离的,使命的处理进程和主库不要紧,便是从库读取:

uri: mongodb://账号:暗码@副本集列表/库实例?authSource=admin&slaveOk=true&replicaSet=shard3&write=1&readPreference=secondaryPreferred&connectTimeoutMS=300000

去掉readPreference=secondaryPreferred试试呢,去掉后默认主库优先,果不其然,功能慢了,它慢了。 那就沿着这个方向向度娘请教了一下,更新了war的读写别离装备,like this:

 <!-- mongodb 查询模板-->
    <mongo:mongo replica-set="${mongo.replica-set}" id="mongo">
        <mongo:options
                connections-per-host="${mongo.connections}" max-wait-time="10000"
                threads-allowed-to-block-for-connection-multiplier="${mongo.threads}"/>
    </mongo:mongo>
    <mongo:db-factory authentication-dbname="${mongo.replica-set.authentication}" dbname="${mongo.name}" mongo-ref="mongo" id="mongoFactory" username="${mongo.replica-set.username}" password="${mongo.replica-set.password}"/>
    >
	<!-- 将mongoTemplate的定义装备上优先由从库读取-->
	<!-- 改前装备-->
    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoFactory"/>
    </bean>
	<!-- 改后装备-->
    <!-- 主要用于处理大数据读写别离:优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据,-->
    <bean id="secondaryPreferredReadPreference" class="com.mongodb.TaggableReadPreference.SecondaryPreferredReadPreference"/>
    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg name="mongoDbFactory" ref="mongoFactory"/>
        <property name="readPreference" ref="secondaryPreferredReadPreference"/>
    </bean>

嗯,布置测试,ok,功能果然上来了,功能根本康复和之前共同了。那这么说起来,仍是主Mongo库的问题了(这个后边和运维沟通了,只要再调查调查,只要你的这块事务目前有问题,先优化事务代码吧),诶,和老迈汇报了这个状况,那终究就依照事务代码优化来做吧。 为了这次改动的影响规模,之前的事务仍是保存保存之前的主库读写,先优化我这个事务由从库读优先吧,所以从头向Spring容器中装备一个新的bean: acBackMongoTemplate,装备如上。

和x团队x同学反馈了,让他们从头建议根据准现网环境的测试使命,验证改动的有效性和精确性,成果15分钟,问题就完美解决了。1天后的服务上线顺带将这个优化需求给上了。

总结: 这次,虽然不是事务这面的问题,可是定位问题的进程仍是比较曲折,作为一个5年的Javaer,短少对这个问题本源的精确定位,中间虽然思考过是数据库的问题,但仍是没找准具体的问题点,导致处理周期蛮长的(其实花费了2-3天才解决),并且虽然通过优化数据库读写别离完结了这次Bug的修复,但问题的本源仍旧还在,只要依靠数据库DBA大佬了,仍是太弱了,学习路程蛮长,持续吧。


后续补充: 时隔几日,具体问题找到了,数据库人员给出的解释:

**mongodb的网卡水晶头松了,从1000M降成了100M,正好遇到守时数据库把宽带占满,导致应用大部分衔接没法衔接数据库。事务大面积无法访问!!!!

记一次D腾的现网数据库问题排查经历,真相是万万没想到!!