先说
今天分享一个之前写的基于redis和kafka实现类似银行叫号
前言
之前作过某风控系统,系统内会设计调用大量的三方数据,导致每一笔风控审核的时候会出现某一笔的消费延迟导致上游的消费速度显著下降,从而出现严重的卡单(kafka)。
确定方案
之前通过kafka消费主要是,并发消费,其类比的生活模式是早期银行排队,也就是kafka队列类似银行的多个窗口。假设银行规定,排队之后不能更换窗口,一个数据类似是来银行排队处理的人,比如如果某一个人出现处理速度过慢,那么有可能出现某一些窗口空闲而其他窗口排队很长的情况,所以当时讨论解决的方案就是将排队改成叫好的模式。当窗口出现可用资源就主动获取资源。
实现
分区和消费数据的流转
数据的获取和流转主要的mq架构还是基于kafka,使用redis来存储kafka的partition,在消费端额外实现一个类似叫号的程序(使用CompletableFuture新启一个线程,通过while循环不断监控redis的资源。大致的代码如下)
@Override
public void run() {
while(true){
log.info("进入while"+(new Date()).toString());
String message =null;
try {
Map<String,Object> messagePattern = configService.getMessagePattern();
if(!(Boolean)messagePattern.get("enable")){
break;
}
log.info("准备获取message"+(new Date()).toString());
message = messageHandlePattern.getAndAck(10L, TimeUnit.SECONDS,this::consume);
});
if(StringUtils.isEmpty(message)){
continue;
}
/**
* 消费之前监控
*/
Date outTime = new Date();
List<Integer> list =redisUtil.rangeUniqueQueue(THIRD_PARTY_RISK_TOPIC_PARTITIONS_LIST,0L,-1L);;
if(list == null){
list = Collections.emptyList();
}
List<String> finalList = list.stream().map(Object::toString).collect(Collectors.toList());