最近一个产品的开发工作告一段落,本文记录开发过程中遇到的几个印象深刻的问题。

数据库查询排序字段问题

问题一 : 排序字段数据重复问题,有一个列表,按时间排序,但是有大量时间相同,导致不同页数据有重叠。

解决办法 :分页查询处理按时间外,再加一个按主键排序的第二排序字段。

问题二 : 排序字段有空值时,导致结果不稳定。 解决办法 :避开空值,例如设置一个默认值,或者排序多加一列。

MyBatis 缓存问题

多模块开发中,有一个模块 A 只读数据库,它依赖另一个模块 B 对某张表进行修改。模块 A 启动时会读取数据库数据,同时用一个定时器查询最新值。

MyBatis 默认配置了缓存,导致模块 A 怎么都查不到最新数据。

解决办法:对于只读的模块,禁用缓存。配置为:

mybatis-plus:
  mapper-locations: classpath*:/mapper/*.xml
  configuration:
    # 开启驼峰命名规则自动转换
    map-underscore-to-camel-case: true
    # 本模块依赖其他模块操作数据库的数据,所以查询禁止缓存
    cache-enabled: false

RestTemplate 超时时间配置

多模块间服务调用时,需要考虑到目标服务器的处理时间,RestTemplate 读取超时时间应该远大于服务器处理的超时时间,保证服务端处理先超时,再返回。

Netty 工作线程资源死锁

有一个多模块通信流程如下:

A 下发数据给 NettyServer,它的 NIO 处理线程跟接收 B 响应的 NIO 线程是同一个,所以是顺次执行的。

而实际上前者依赖后者更新下发结果,A 下发线程得不到响应结果后超时返回,规则响应线程此时才能继续更新缓存中 B 的结果,但是已经晚了,形成了一种资源等待死锁现象。

解决办法:调整 A 发送的流程,调用 serviceB 下发和等待响应的逻辑放入新线程中处理,释放 NIO 工作线程资源。

事务嵌套子事务未提交问题

有一个嵌套事务,前提是不希望 serviceB 的数据随着 serviceA 的异常回滚,所以在 serviceB 上添加了Spring 的事务注解,开启新事务。

但是 serviceA 的步骤2依赖插入的数据,而查询操作不会触发 serviceB 上事务的提交,导数数据不一致问题。

这就引发了嵌套事务的提交问题,解决办法,去掉 serviceB 的事务,或者在 serviceB 中用 TransactionTemplate 显式执行事务,可以保证其写入操作及时提交。

  • 私信