首先,大的架构,是异步。怎么异步?为什么异步?
为什么异步?
因为对接第三方。
当然,对接第三方,也可以不异步。但是显然不是一个好的设计,因为一般来说,大部分业务场景,只要是对接第三方,那么你的上游(也就是你要对接的第三方),也极有可能是对接其他的第三方,比如支付公司。所以,他都是一环扣一环的,如果只有两个系统对接,比如公司内部系统之间的接口对接,那么可以同步,如果是对接外面的公司的接口,一般都是异步。
一方面是业务场景需要。
一方面是你的上游也要对接其他上游,他都不能即时的给你同步响应,你怎么能给你的下游即时同步响应呢。
还有一方面,是因为异步可以解耦。异步之后,意味着数据可以多次处理,如果数据处理有问题的话。比如,支付了之后,查询支付状态,这个接口是要查询多次的,可能。还有,解耦可以降低系统的处理压力。因为你把处理时间拉长了,肯定就可以缓解当前的一时的处理压力。也就是说,你先把数据存储到本地,然后慢慢处理本地数据。
怎么异步?
1.定时任务。
2.定时任务 + 多线程。
for循环处理数据
只有定时任务,没有多线程。 //充值。为什么充值不需要多线程?数据不是很多,就没有必要使用多线程,可以不使用多线程。
这种是最简单的实现。连多线程都没有。
多线程处理数据
定时任务 + 线程池 //多线程就是线程池
1.固定线程池 //转账
2.core max线程池 //实名认证
3.生产者 消费者模式 //支付
线程池,固定线程池,core max线程池,都差不多。
阻塞队列
为什么实名认证,用了阻塞队列?数据比较少。至少没有支付 转账数据那么多。转账是使用默认链表阻塞队列,默认大小是无限大。支付是生产者 消费者两个进程,用的是非阻塞队列-并发链表队列。
/** 10个线程检查异步订单,当队列满了之后,等待 */
protected static Executor executor = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1000),//阻塞队列集合
new RejectedExecutionHandler() { //
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
if (!executor.isShutdown()) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
log.error(e.getMessage(), e);
}
}
}
});
生产者 消费者
为什么支付,要使用生产者 消费者?生产者 消费者的优点优势?到底是解决了什么问题? 1.读数据库和写数据库解耦,分别由两个进程处理 2.写队列和读队列解耦,分别由两个进程处理
充值
用的最简单的,定时任务。for循环处理数据。
转账
定时任务 + 多线程(线程池)。//固定线程池。其他三个参数,默认值。//阻塞队列的任务数量是无限大,因为转账的数据比较大。
实名认证
定时任务 + 多线程。//参数自己配置。阻塞队列。//阻塞队列的值是自己配置的1000,因为实名认证的数据比较少。
支付
定时任务 + 生产者/消费者。