问题背景
物联网场景下,平台给设备下发命令。同时给一个设备下发命令时会导致命令一个成功一个失败。
需求
1、按设备实现命令的对列发送,一个发送成功在发送下一个
2、命令有优先级,优先级高的命令可以实现插队
3、命令发送后8秒如果未收到回复认为发送失败
物联网场景下,平台给设备下发命令。同时给一个设备下发命令时会导致命令一个成功一个失败。
1、按设备实现命令的对列发送,一个发送成功在发送下一个
2、命令有优先级,优先级高的命令可以实现插队
3、命令发送后8秒如果未收到回复认为发送失败
解决方案:
方案一:
使用Redis + MQ + 任务调度;业务伪逻辑:
1、封装统一发送命令的接口,入参为命令抽象对象集合、设备ID。命令抽象对象集合有优先级字段
2、对命令集合进行排序
3、设备ID最为redis的Key,判断redis中是否已存在,如果不存在,则直接推送MQ,注意MQ使用事务消息,这样可以避免8秒等待
4、如果redis中有该设备ID,去除value,value为已发送成功的命令,循环判断当前命令是否已存在,若已存在则跳过,否则继续发送MQ,并将成功的发送的MQ添加到该value集合里
5、推送MQ失败的命令单独封装为一个有设备ID和命令的对象,并存储到redis或持久化到DB中,使用任务调度补偿重试
方案二:
线程池 + 线程安全队列
1、使用线程池管理要推送的命令集合,每一个线程对应一个设备ID
2、要推送的命令集合进行去重和排序
3、使用有界队列避免内存损耗,自定义拒绝策略,避免命令丢失
4、要推送的命令集合注意使用线程安全的队列
5、任何线程都等待8秒响应,不要释放资源,如果发送失败,则存放到失败的共享数据源里
6、单独起一个线程,比如守护线程,对发送失败的数据进行重试机制
这是我目前能想到的,推荐方案一,方案二存在集群环境的风险。 如果不明白可以私信讨论