关于定时短信服务的讨论
事情的起因
需求:每次线下活动前一天晚上7:00向已报名参加价值学习俱乐部的用户发送通知短信,以便用户记得准时参加活动。
注意:因为我们的业务并发量不是很大,很多场景没有考虑到并发情况下的一些问题。 这个需求只是通过crontab来执行,再加上服务器的自动弹性伸缩,就相当于模拟了一个并发业务。 场景。
首先简单介绍一下数据库的表结构:
这些解决方案都依赖于每天晚上 7 点执行 corntab。
计划1
根据讲座开始时间查看活动表中是否有符合条件的线下活动。 如果有,则将activity id关联到sign-in表,过滤掉sendms字段为0的uid,并关联到user表,取出手机号等信息。 发送完成后,sendms字段会统一更新。
缺点:并发业务场景下,可能会出现脏读,导致发送多条短信。
场景2
与方案一非常相似,唯一的区别是查询时启用了事务。 该查询语句的不同之处在于sms短信群发定时短信软件,在 SELECT 期间锁定结果行,从而避免脏读,然后在同一事务中 UPDATE send_sms 字段。 ,最后“提交”。
缺点:由于发送短信不是数据库操作,因此无法回滚。 因此sms短信群发定时短信软件,如果执行过程中出现回滚,就会出现短信已经发送,但是数据库回滚,send_sms字段被设置为0,这样就产生了矛盾。 而如果是一项耗时的任务,则可能会出现死锁问题。
以下是执行逻辑
BEGIN; SELECT ... FOR UPDATE; UPDATE ... SET send_sms = 1; COMMIT;
选项3
与方案2非常类似,唯一的区别是,将数据一一取出,锁定,然后更新send_sms字段。
缺点:需要写一个循环来查询满足条件但尚未发送短信的用户。 如果处理不好,很容易导致死循环和死锁。
选项4
这是我目前能想到的最好的解决方案。 使用SELECT语句直接选择所有符合条件的手机号码和短信内容,放入Queue中,然后对Queue进行处理。 处理过程如下:首先使用SELECT ... FOR UPDATE确定send_sms字段的值。 如果为0,则发送短信,然后将send_sms字段更新为1,最后COMMIT。 这避免了多次执行短信的需要。
总结:对于实时性要求不那么高的业务场景,使用Queue是非常方便的。 让Queue一一处理,这在复杂系统中也起到了调峰、解耦的作用。 您的工作中有哪些 Queue 的应用? 欢迎留言一起讨论!
对于上述解决方案您有什么建议? 欢迎留言讨论!