曾接触到一个报文发送的项目,这个项目的报文发送,虽有报文优先级,但却无按照报文优先级发送的功能。
因此,我便思考了一下,将自己的设计思路发出来,与大家共享。
首先明确的是,我所设想的报文发送是基于 Redis的 SortedSet 数据存储结构,之所以可以选择这个结构是因为每个报文都有不同的id。
报文有三个优先级:高、中、低;报文有两个类型:定时发送报文和普通发送报文。
因之前并未深入接触过redis,在redis中 sortedSet 提供了自动排序的功能,那么之前的一堆设计均可以忽略掉。可以直接使用该特性来设计。
报文优先级:普通报文集合 高、中、低 使用同一个集合,并设置不同的权重
定时报文集合 定时报文按照发送时间戳设置权重,最小的时间戳权重最高(计算方式使用 2099年1月1日 减去该报文时间戳)
需要的线程及其所实现的功能:
普通报文获取线程,直接按配置数量获取报文,并删除redis缓存相应数量的报文,使用LPOP
定时报文获取线程,直接获取最高权重的报文,并获取该报文的时间戳,比较该时间戳是否需要发送,需要发送,则保留且删除缓存该报文 ZREM
,不需要则sleep(1000)后再获取
这样获取到报文后,直接等待发送线程消费即可。
这两个线程获取报文均有一个上限配置。
这两个线程获取到报文后,等待wait,未获取到任何报文时,则sleep(1000)后再获取。
发送线程: 在每个发送周期(串行的),优先获取定时队列的报文,未获取到,则获取普通队列报文;发送后,将报文放入回调线程访问MAP中。
回调线程: 若发送异常,回调报文状态变为异常。
定时处理异常线程:自动搜集当前时间之前的,发送异常的报文,根据(异常规则)判断报文是否可以再次发送,如果可发送,则放入普通报文集合,否则不发送,并将状态置为发送失败。