日常技术总结

187 阅读7分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

技术总结(不定期更新)

记录我的日常工作的技术总结,属于个人感悟,不定期更新

代码开发

接口篇

  • 接口支持高级分页(数据量过大深分页问题)

分页可以减少客户端接收的数据数目,但是当你需要将分页结果与不断接收的新条目结合时,通常的限制limit和偏移offset分页参数是低效的,因为每次当有个新条目在服务端被添加到先前的集合时,先前发送到客户端的偏移offset都变得无效,而且客户端无法得知在两次请求间新增了多少条目。保持客户端同步一个比较好的办法是使用before_id和after_id参数组合,比如客户端将已知的最新条目的id作为after_id请求参数,然后检索之后创建的新条目(当分页结果总数比较大时,获取靠后的分页结果会及其的慢,因为offset分页已经效率很低了,即使已经加了索引——实际工作场景中遇到的是要获取一个总数为10万的分页结果[该表做了8个分库操作],每页500条数据,当获取靠后页码的分页结果时,查询效率已经很低了,有的甚至超过了5秒,这对于分布式系统是无法接受的)

  • 提供了分页的外部接口就不要再提供查询总数接口

过多的给外部提供接口会让后期维护成本变得更高,会使得难以管理和改动

  • 为什么服务提供方不适合提供大批量的调用接口
  • 背景:根据多区域查询用户数据信息的接口,可传区域数量限制是5个,对于某些业务场景来说太少,比如运营有上百个区域,调用方就需要调用多次,会影响性能,想要服务提供方将这个限制放大些(简单的来说,就是提供了一个批量查询的接口,为了兼顾能快速响应给服务调用方,入参中批量的列表只支持5个,但是调用方因为业务场景需要调用多次,希望调用提供方来调大批量的个数限制减少调用次数)
  • 解释:该问题可以从技术维度探讨一下,建议可以设置个阈值做并行的循环调用(需要客户端和服务端支持动态调整阈值,该阈值用来调整批量的数量限制)。我们不妨使用反向论证法来剖析一下,考量点是这样,假如把大批量的逻辑放到服务提供方,可以有两种实现方式:其一是串行,其二是并行。串行肯定不能满足性能要求,会把调用端拖死,基本不能解决超时的问题,并行会存在计算量大,CPU压力大,会把CPU跑满。基于以上弊端,建议把并行放在客户端,客户端不存在计算的压力,循环后通过RPC的负载均衡会打到服务提供方集群的多个机器上,这样服务提供方的压力做了分散,理论上可以通过该集群的扩展获取想要的流量

MQ篇

  • 如果MQ由于种种原因无法保证数据库操作和发MQ在同一个事务下保证,则必须先进行数据库事务操作,再发MQ
  1. 如果先发送MQ再进行数据库事务操作,则可能会造成MQ已经发送成功,数据库事务提交失败,此种错误不易进行补偿
  2. 如果先进行数据库事务操作,则发送MQ,当MQ发送失败,需要记录失败日志,同时进行告警或者通知到相关人员,进行MQ重发操作进行补偿
  3. 如果是使用的MQ本地消息表或者其他方式能够保证数据库事务和MQ在同一事务,则无需关心此问题(RocketMQ、Seata、Hmily等来解决)
  • MQ同一业务数据状态保证顺序:保证同一业务主键的MQ能落到同一个分区上,需要有一个路由策略组件,由它决定消息该放到哪个分区中。生产者可以根据topic的路由信息选择具体发到哪个queue上,consumer订阅消息时,会根据负载均衡策略决定订阅哪些queue的消息
  1. 用户的等级状态:根据用户的行为(如GMV、下单件数、下单笔数、注册时间等)圈定用户,并根据圈定阶梯发送MQ为用户更新等级,但是用户在多个圈定行为中重复存在,这时就要根据发送MQ的顺序确定一个最终等级,这时就需要用户的id作为主键,将同一用户id的多个等级按照顺序进行发送MQ到同一个分区上
  2. 用户的订单状态:一个订单会产生多条MQ消息,下单、付款、发货、买家确认收货,消费端需要严格按照业务状态机的顺序处理,否则,就会出现业务问题,只要保证一个订单的多条状态消息在同一个分区,便可以满足业务需求,所以我们可以以订单id作为MQ的业务主键,保障同一订单的多个MQ消息可以落到同一个分区上
  • MQ生产速度大于消费速度产生消息积压:增加分区数(同时消费者数要大于等于分区数)、增加消费方每次拉取待消费的MQ数
  1. 如果仅仅只有一个分区或者较少的分区造成了消息的积压,可考虑增加分区的方式,提高消费方的消费速度。对于同一个消费组,一个分区只支持一个消费线程来消费消息。过少的分区,会导致消费速度大大落后于消息的生产速度,可能会造成消息的积压。所以在实际生产环境中,一个topic会设置成多分区的模式,来支持多个消费者
  2. 适量增加每次一次性从broker里面取的待消费的消息的个数
  • 过大量级的MQ消息量一定要进行业务前置过滤,否则可能造成消息挤压或者消费者机器宕机
  1. 当比较通用的MQ(比如订单、红包、优惠券、答题结果等)需要接入时,一定要根据业务类型进行过滤,通用型的MQ一般数据量都会特别大,每天的量可能达到上亿级
  2. 接入埋点上报的MQ要进行业务前置过滤:埋点的MQ消息量也十分的庞大,可以进行业务逻辑的校验提前过滤掉无需往下处理的MQ
  • MQ并发消费需要根据业务主键进行加锁和解锁,锁的粒度一定要最小

如订单类MQ接入,同一个订单有可能取消的消息先到,所以我们需要对这样的订单MQ进行并发处理,根据订单id进行加锁(同时要指定过期时间,过期时间长短可以视业务而定),当该订单的业务处理完毕,再根据订单id进行解锁,当同一个订单(重复或其他状态)的MQ过来,可以保障并发时的先后顺序

PageHepler篇

  • PageHelper对需要分页的方法不生效
  • 简略写法可不使用PageInfo
  • 查询出的列表结果额外属性赋值
  • PageHelper深分页效率问题

指导文章

专题文章

梁的主页

非专题文章

大厂技术

美团技术github

  • 配置中心——MCC
  • PRC——Mthrift(基于thrift)
  • 任务调度——Crane
  • 分布式监控——CAT【开源】
  • 内部知识网——学城(大佬技术文章都有,有广度有深度)
  • 缓存——squirrel(基于Redis)
  • MySQL访问——Zebra【开源】

京东技术(gitee

  • 配置中心——DUCC
  • PRC——JSF(基于Dubbo)
  • 任务调度——天鸽(基于xxl-job)
  • 分布式监控——UMP
  • 内部知识网——CF
  • 缓存——JIMDB(基于Redis)

百度技术(gitee