redis实现消息队列

工作中遇到一个业务场景,A系统会批量刷新主数据,每次以单条传递到我的系统B(A系统没有办法做一次传多条主数据信息),并且有时传递的数据会有顺序要求;
最近批量同步主数据系统时,出现了B没有可用连接提供给A;

  • 原因:大概是这样的,B系统每接收到一个请求,首先校验是否存在编号,存在做更新,不存在做插入,完事之后再同步给另外一个系统;
    系统B是多节点部署,在判断是在做更新或插入时,有并发问题,所以对编码进行了加锁处理;导致有些相同编码持有连接无法释放,耗尽系统资源;

1.使用MQ进行削峰

这种问题也只有在批量刷新主数据的时候才会有,平时的少数更新或插入不会出现这种问题;
想到使用MQ进行削峰,如果是使用DDMQ/RabbitMQ感觉有些小题大做,所以采用redis的队列进行处理;

2.redis实现消息队列

redis提供了list类型,此类型底层是通过双向链表来实现:

lpush、rpop 非阻塞式
blpop、brpop 阻塞式

先来对比一下上面阻塞与非阻塞会有什么问题;

1.阻塞式:如果队列里面没有消息,会阻塞连接,长时间占用redis连接,需要考虑redis配置的超时以及redis会对空闲连接进行释放以减少资源浪费,需要对异常进行捕获重试;
2.非阻塞式:如果是1s主动去redis中拉取一次消息,也不太适合;

解决方案:

1.存数据时,采用rpush,从右边添加;
2.取数据时:从左边lrange key 0 100; 每次拉取100条;程序定时1分钟拉一次;

存在的问题

1.上一个定时任务执行没有执行完毕,下一个定时任务会执行吗? 验证:不会;
2.如果拉取100条在处理,程序突然停机,怎么办?拉取100条后,每处理完成1条,就从list中将本条删除;lpop
3.多节点拉取redis list中的数据,怎么保证不会重复?
两台节点,提供了两个list,在rpush时,首先对编码进行hash,来决定放入哪个list中,两台消费节点,一台消费一个list;