业务代码里也开始用算法了吗?这是不是出息了?
摘要:你好呀,我是歪歪。 好消息,好消息,歪师傅最近写业务代码的时候,遇到一个可以优化的点。 然后,灵机一动,想到一个现成的算法可以拿来用。 业务代码中能用到算法,虽然不是头一遭,但是也真的是算难得了。 记录一下,分享一波。 走起。 场景 场景是
你好呀,我是歪歪。
好消息,好消息,歪师傅最近写业务代码的时候,遇到一个可以优化的点。
然后,灵机一动,想到一个现成的算法可以拿来用。
业务代码中能用到算法,虽然不是头一遭,但是也真的是算难得了。
记录一下,分享一波。
走起。
场景
场景是这样的。
首先,我有一批数据要调用下游系统的一个统一的接口,去查询数据状态。
这一批数据,分属于不同的平台,所以调用下游查询接口的时候,我会告诉它有的数据要去 A 平台查询,有的数据要去 B 平台查询...
大概就是这个意思:
在这个场景下,我们还不用关心平台方的同步返回结果,因为最终的结果平台方会异步通知回来。
这样看起来是一个非常简单的场景对不对?
现在我们在这个基础上加一个小小的变化。
由于这个下游系统是一个非常重要的系统,承担着全公司所流量的出人口,可以说是咽喉要道。
所以,出于保护自身的目的,它对调用方的接口都做了限流。
对于我这个小卡拉米的、边边角角的查询动作,它给的限流就是一秒最多一笔。
也就是说,我调用查询接口的时候,线程池什么的就别想了,老老实实的排队,然后一秒一个的发请求,
大概就是这个意思:
这样看着也没有问题,一秒一个控制起来还不简单吗?
优雅一点的,你就上个限流器,八股文翻出来一看,什么信号量、令牌桶、Guava RateLimiter 随便掏一个出来用就行了。
糙一点的,你直接 for 循环里面 sleep 一秒也不是不可以。
我是一个糙人,所以我直接选择 sleep,大道至简。
伪代码大概是这样的:
//伪代码:从数据库获取某平台数据后,在循环中每秒调用一次下游接口
publicvoidprocessDataWithDelay(){
//1.从数据库获取数据(示例使用伪方法)
List<DataObject>dataList=database.fetchData("A");//假设返回数据列表
//2.遍历每条数据
for(DataObjectdata:dataList){
try{
//3.休眠1秒(1000毫秒)
Thread.sleep(1000);
//4.调用下游系统查询接口
downstreamService.query(data.getId());
}catch(Exceptione){
}
}
}
整体来说就是先把一个平台的数据全部处理完成后,再处理下一个平台的数据。
用图说话大概就是这样的:
这样看着也没有毛病。
但是,有一天,A 平台找过来说:哥们,你们这个查询有点太快了,1s 一个查得我有点扛不住。能不能调一下,比如调成 6s 一次?
本来我想追问一下:就这么差劲儿吗,一个查询接口,一秒一个都扛不住?
但是本着程序员不难为程序员的原则,我还是忍住了。
6s 一次,这还不简单嘛。
我把前面伪代码中的 1000ms,修改成配置项,默认为 1000ms,如果某个平台有个性化需求,我直接给对应平台的配置一个专属的间隔时间就行了:
//伪代码:从数据库获取某平台数据后,在循环中每秒调用一次下游接口
publicvoidprocessDataWithDelay(){
//1.从数据库获取A平台数据(示例使用伪方法)
List<DataObject>dataList=database.fetchData("A平台");//假设返回数据列表
//2.从数据库获取A平台休眠时间配置(毫秒)
intsleepInterval=getSleepIntervalFromConfig("A平台");
for(DataObjectdata:dataList){
try{
//3.休眠
Thread.sleep(sleepInterval);
//4.调用下游系统查询接口
downstreamService.query(data.getId());
}catch(Exceptione){
}
}
}
用图说话就是这样的:
是不是完美的解决了 A 平台的问题?
但是,你想想这个调整之后,带来的新问题是什么?
A 平台假设 100 条数据,之前一秒一个,100 秒就发完了,然后 B、C 平台的数据就能接着处理了。
现在 A 平台的 100 条数据要发 600 秒,由于是排着队串行执行,导致 B、C 平台的数据,都因为 A 平台处理慢了,得跟着慢。
整个数据处理的事件周期就长了。
而且实际情况是更长,因为每次处理的时候,A 平台不止 100 条数据,基本上都是好几千条。平台也不只是 A、B、C 三家,而是有好几家。
怎么办?
遇到事情不要慌,三思而后行。
能不能不做?能不能给别人做?能不能晚点做?
我也三思了,具体是这样的。
