- 通常情况下,出现消息积压的原因有
- mq消费者挂了
- mq生产者生产消息的速度,大于mq消费者消费消息的速度
- 当数据量不大时,优化消费者处理逻辑
- 通过在代码中增加了一些日志,把mq消费者中各个关键节点的耗时都打印出来,发现有两个地方耗时比较长
- 有个代码是一个for循环中,一个个查询数据库处理数据的
- 有个多条件查询数据的代码
- 解决方案:
- 将在for循环中一个个查询数据库的代码,改成通过参数集合,批量查询数据
- 多条件查询数据的地方,增加了一个联合索引
- 这样优化之后,mq消费者处理消息的速度提升了很多,消息积压问题被解决
- 通过在代码中增加了一些日志,把mq消费者中各个关键节点的耗时都打印出来,发现有两个地方耗时比较长
- sql语句执行的where条件是一样的,只有条件后面的参数值不一样,导致sql语句走的索引不一样
- 比如:order_id =123走了索引a,而order_id=124走了索引b
- 有张表查询的场景很多,当时为了满足不同的业务场景,加了多个联合索引
- mysql会根据下面几个因素选择素索引:
- 通过采样数据来估算需要扫描的行数,如果扫描的行数多,那可能IO次数会更多,对cpu的消耗也更大
- 是否会使用临时表,如果使用临时表也会影响查询速度
- 是否需要排序,如果需要排序择业会影响查询速度
- 总合123以及其他一些因素,mysql优化器会选出他自己认为最合适的索引
- mysql优化器是通过采样预估要扫描的行数的,所谓采样就是选择一些数据页来进行统计预估,这个会有一定的误差
- 由于MVCC会有多个版本的数据页,比如删除一些数据,但是这些数据由于还在其他的事务中可能会被看到,索引不是真正的删除,这种情况也会导致统计不准确,从而影响优化器的判断
- 上面这两个原因导致mysql在执行sql语句时,会选错索引
- 明明使用索引a的时候,执行效率更高,但实际情况却使用了索引b
- 为了解决mysql选错索引的问题,我们使用了关键字force index,来强制查询sql走索引a
- 数据量太大,查询太慢
- 通常情况下,单表的数据太多,无论是查询,还是写入的性能,都会下降
- 解决方案:
- 做分库分表
- 将历史数据备份
- 表中只保留最近30天的数据,超过几天的数据写入到历史表中
- 这样优化之后,表30天的数据量就小了很多,对性能影响不大
- 当上游系统执行批量修改订单状态的job,这个状态修改会发送mq给下游
- 这样导致,在极短的时间内,产生了大量的mq消息
- 而我们的mq消费者根本无法处理这些消息,所以才会产生消息积压的问题
- 解决方案:
- 增加partition数量
- 使用线程池处理消息
- 由于消息已经积压到几个已有的partition中了,再新增partition意义不大
- 为了开始消费积压的消息,我们将线程池的核心线程和最大线程数量调到了50
- 解决问题之后,我们还是保留的线程池消费消息的逻辑,将核心线程数调到8,最大线程数调到10
- 后面出现消息积压问题,可以及时通过调整线程数量,先临时解决问题