纯技术每日一题

纯技术每日一题

一、11/4 (token、过期、分布式、多个节点多次调用)

业务背景

小猛同学正在压测,发现个小问题,因为在终端设备上跟鹅厂有紧密合作,调用他们的接口时需要获取到access_token,但是这个access_token过期时间是2小时,过期后需要重新获取。

压测时发现当到达过期时间时,日志看刷出来好几个不一样的access_token,因为这个服务也是分布式部署的,多个节点同时发起了第三方接口请求导致。

虽然以最后一次获取的access_token为准,也没什么不良副作用,但是会导致多次不必要的对第三方接口的调用,也会短时间内造成access_token的 重复无效获取

讨论

  • 调用三方接口获取 只能有一个线程去调取三方接口获取 取到后放入缓存 其他的线程一直从缓存中取

  • 这个感觉应该用分布式锁把。默认从缓存取,缓存没有去获取锁。没拿到,等待一下。拿到了。在判断缓存有没有,有的话直接返回了,没有的话去重新申请,添加到缓存,然后释放锁。其他进程一样操作。

  • 嗯嗯,出现多余的access_token,是因为2个小时到了,多次请求,同时判断需要更新access_token了,那肯定就得只能让一个请求获取到access_token,其他的等待,然后再拿access_token,才能保持一致;这种肯定是是全局锁,加内部锁的,双重锁检查;但是性能会不会出现问题呢,不好说;

  • 你加锁影响并发 你不如生成两个 第一个失效了 就用第二个 ,然后再存一个备用。两个放进去 一个失效了直接取出来第二个

  • token加计时器,大部分走分布式取token,快2小时时走单线程取token。

  • 直接用etcd存储token , 设置失效时间,token失效会直接etcd推送事件,再次刷新token即可

  • 这个让我想起了netty时间伦

  • 不能所有东西都用分布式锁的 那个太影响性能了

  • 提前生成的话,需要程序中创建定时器,这个逻辑不能兜底啊,那如果定时器创建失败或者程序重启呢。还是会有获取多个token问题

  • 你看中间件的源码 有没有什么问题都优先考虑分布式锁 基本上都没有那玩意,锁都是迫不得已的解决办法

  • 为啥没人讨论 etcd的 Watch 机制:即监听机制,Watch 机制支持 Watch 某个固定的 key,也支持 Watch 一个目录(前缀机制),当被 Watch 的 key 或目录发生变化,客户端将收到通知。这个有被用技能啊

  • 虽然以最后一次获取的access_token为准,也没什么不良副作用,但是会导致多次不必要的对第三方接口的调用,也会短时间内造成access_token的 重复无效获取

    这个思考题的题干,是说会导致多次不必要的对第三方的接口的调用,目标是为了减少不必要的调用吧?

优秀方案

  1. 方法一

    纯技术每日一题

  2. 没最优的解决方案,最优最合适业务场景的,这个是其他的方式:

    1、不使用db,查询redis 中access_token,存在直接返回;不存在,加分布式锁,同时检查是否存在,存在返回;不存在调用第三方接口,写redis,同时设置对应的过期时间

    2、后台定时任务去刷新access_token,同时失败后去调用一次接口(容错)

    3、图上群友提供答案中为啥需要db?有些同学考虑到redis宕机的场景或者主从数据丢失的场景,也可以用db来进行兜底

二、11/4 (大数据、高并发、mysql同步、库结构不一致)

业务背景

小猛同学在某公司的大数据部门,现在要做一个高并发的同步系统,把某个业务的数据同步到自己的系统中,然后在做各种复杂的操作后提供接口给其他部门查询,每天日同步数据要达到上千万级别。

整个数据同步前期流程是从一个 mysql 库原封不动地同步到另一个 mysql 库里面去(mysql -> mysql)。

小猛同学初步架构设计是:从一个mysql监听到binlog后发送消息到MQ中,另外一个服务在消费MQ中的数据写到自己的库中,但是现在存在一个问题。

多个业务系统执行sql往mysql 里增删改对应的数据,但是小猛发现自己这边库的数据有时候跟业务方的库数据不一致。

讨论

  • mq顺序性可能,也可能消息处理的慢了 导致中间的延迟性的数据不一致
  • 坐听大神们的答案,最近我们公司在搞 三合一,三个库的数据同步一个库
  • 其实是数据迁移涉及两点:(1)历史数据迁移 (2)实时数据迁移
  • 如果要强一致性效率上就比较差了,要强一致性 只能 1个生产者1个队列1个消费者

优秀方案

  1. 纯技术每日一题

  2. 纯技术每日一题

  3. 其他:

    1、小猛同学是使用的RocketMQ,在监听binlog的服务中发送消息到RocketMQ的时候,一条数据的增删改路由到同一个messagequeue中保证消息的顺序性;

    2、A同学会问:如何解决监听到binlog后发送消息到RocketMQ的失败问题呢? 答:发送消息时重试、多次重试失败后,提供兜底补偿方案

    3、B同学会问:发送binlog01、binlog02,01发送失败重试,02发送成功到时无序怎么办?答:修改MQ的配置,需要等消息01发送成功后才能发送02;或者修改binlog为row模式,不使用insert update delete等逻辑上的binlog

    4、C同学会问:如何保证MQ中的消息不丢失?答:RocketMQ的master、slave高可用,基于一致性算法raft来写commitlog

    5、D同学会问:如何保证消费messagequeue时消息的有序性?答:单线程消费;如何提升系统性能?答:单线程消费后,路由到队列中,在每个队列一个线程消费。如何解决数据丢失问题?答:ack机制、优雅停机

    6、E同学会问:消费方执行本地落库的事务成功了,但是ack的时候失败,有重复消费怎么办? 答:在消费方来保证幂等

    7、F同学会问:为啥要单独在搞个MQ直接用同步工具不就好了吗?答:比如alibaba otter、离线dataX、kettle等

    8、补充说明:整个数据同步过程中,还是需要定期的比对数据;定期的全量同步数据;

上一篇:Access、SQLServer以及SQLite如何查询数据表结构


下一篇:Nginx解决跨域问题No 'Access-Control-Allow-Origin'