背景介绍
实现预约功能,顾客预约饭店以后,等到预约时间后系统会调用一个接口通知商家有预约的订单到期了。为了实现该功能需要开发一个能够实时监控预约并回调指定接口。即延时回调服务。
解决方案
1、通过订阅redis key的过期事件来预约提醒。
2、为了防止redis出现故障,使用慢轮询对数据库的预约数据进行二次处理。
下图为延时回调的流程图
基本流程:
1、通过延时回调服务将预约的时间、回调地址以及参数传入。
2、回调服务将预约信息插入数据库并将id保存到redis中,同时设置key的过期时间。
3、如果有key过期,redis会发送消息通知延时回调服务key过期了。
4、延时回调通过key上数据库查找对应的回调地址并执行http调用。
Redis过期时间的订阅以及处理
该服务使用的时springboot相关的组件,但其他的redis客户端也都含有redis事件订阅的方法。本示例springboot。
JedisConnectionFactory jcf = (JedisConnectionFactory) redisTemplate.getConnectionFactory();
jcf.getConnection().pSubscribe(new MessageListener() {
@Override
public void onMessage(Message message, byte[] pattern) {
//此处为业务处理代码,注意需要对redis key进行过滤
}
}, "__keyevent*__:expired".getBytes());
结束语
为了减少轮询数据库带来的压力,有很多方案。比如使用RabbitMQ实现延时队列,阿里云的消息服务列等等。为了保障系统的高可用,防止redis挂掉或者重启,最好有一个保护机制,比如起一个线程轮询数据库,但是频率要低一些几分钟一次即可,这样可以最大限度的保证系统的正常运行。但是如果实时性要求很高就需要考虑其他方案了。