问题背景

很多人可能会留意到, 关注了公众号之后,隔一段时间, 公众号会推送消息出来,打开消息后发现这些消息看起来不像人工发送的,应该是设计好的一套关注后的定时推送机制, 从而来达到获客转化的目的.
我司微星极光的一个重磅产品, 公众号激活宝, 目前就以第三方平台的形式给各个服务号公众号提供了这样的赋能.

效果如下图

本文主要介绍如何实现这种推送机制的技术方案

技术选型思路

定时调度数据库轮询

这种是很容易想到方案, 有点是简单粗暴, 缺点也同样明显, 效率低下, 适合在用户量很少的时候,顶一顶. 一般草根团队在PoC阶段凑和用的, 我们微信极光公众号激活宝这个产品, 开发这个功能的时候, 已经积累了非常多的用户量, 这里显然不合适, 所以pass掉了

使用golang defer timmer

他们第三方平台的后台语言使用Golang, 这个也是一开始尝试过的方案, 非常灵巧, 见效快.

timer = time.AfterFunc(time.Duration(n) * time.Minute, func() {// do something
})
defer timer.Stop()

但是这个方案有2个缺点

  1. 进程重启后, 定时的调度信息丢失.
  2. 不支持分布式, 有时候会有重复推送.

所以虽然实现起来超级简单, 但可用性没达标, 最后pass

使用Linux时间轮

golang defer timmer的底层是linux时间轮, 为了解决分布式的本质问题, 研究了时间轮的实现.

最简单的时间轮, 可以拿钟表比喻, 比如有的任务固定在15分钟的时候触发, 那么这些任务就排队盯着15分钟这个维度, 等着时间点到, 就触发链表挨个调用函数, 如下图

上面的简单模型有一个问题, 就是刻度是均匀的, 而且范围也有限, 而实际情况中呢, 我们会有不同的刻度(时间粒度)计时, 而且时间范围跨度也会很大.这种情况下像是个水表, 不同粒度有着不同的触发周期.时间以固定 tick 递增,而当前时间指针则也依次递增,如果发现当前指针的位置可以确定为一个注册的定时器,就触发其注册的回调函数.

linux的时间轮数据结构,如下, 内核的定时器本质上是 Single-Shot Timer,如果想成为 Repeating Timer,可以在注册的回调函数中再次的注册自己

结论, 时间轮是一切定时任务的核心底层逻辑, 但是对于应用层来说, 显然用起来还是不够方便, 应该有更易于使用的形式存在.

使用AWS的SQS消息队列服务

AWS的SQS提供delay的支持, 非常完美得解决了这个问题,

接口调用也很简单

System.out.println("Sending a message with a 5-second timer to MyQueue.\n");
SendMessageRequest request = new SendMessageRequest(myQueueUrl, "This is my message text.");
request.setDelaySeconds(5);
sqs.sendMessage(request);

有点是调用简单, 一个月有100万条消息的免费额度,
缺点是超过配额之后, 费用还是挺贵的.

使用redis的redis key notification功能

Redis在2.8版本以后, 支持了一个特性, 叫Keyspace Notifications.

通过Pub/Sub的机制, 设置TTL, 然后另外的进程来监控Expired事件, 从而达到delay message的目的.
值得注意的是, 官方文档有这样的描述.

Because Redis Pub/Sub is fire and forget currently there is no way to use this feature if your application demands reliable notification of events, that is, if your Pub/Sub client disconnects, and reconnects later, all the events delivered during the time the client was disconnected are lost.

Redis提供的这个事件回调,并不承诺可靠.

使用RabbitMq实现延时队列

AMQP协议和RabbitMQ队列本身没有直接支持延迟队列功能,但是可以通过以下特性模拟出延迟队列的功能.

  • TTL(Time to Live)
  • DLX(Dead Letter Exchanges)

简单而言就是对每条消息设置TTL, TTL就是延迟的秒数. 然后消息到期后, 进入死信队列,
死信队列里面再进行规则转发.
原理就是这么个原理, 这个需求挺通用的, RabbitMq官方也给出了一个插件rabbitmq-delayed-message-exchange.

使用起来在header里面x-delay加上延迟的秒数就行

headers.put("x-delay", 5000)

实战方案

在实际的过程中呢, 我们最先使用的是AWS的SQS, 后来业务起来了,发现免费的100万一个月不够用, bill的账单数字还挺吓人的, 于是改成自研的方案.

因为历史积累, 我们重度使用redis, 于是入坑了redis的keyspace notifications的方案, sofar so good, 直到有2个问题暴露出来,

一个就是官方文档提到的, reconnect的之后, 不保证可靠性, 这个监控显示有概率非常小发生, 不到十万分之一, 对比了机器的环境, 应该是和网络抖动有关, 这个小概率的修复, 目前我们吞下了.

第二个问题就是因为redis是内存型的, 如果有一些公众号粉突然爆粉的时候, 会导致redis的key暴增, 进而导致内存暴增. 而redis并不支持弹性伸缩, 导致一度非常蛋疼.经常收到告警, 半夜爬起来手工处理.

第二个问题后来通过keydb来解决了, keydb 里面有个flash功能, 非常切合我们的业务, 业务其实我们并不需要很高的内存, 把这些key扔到flash disk里面, 可以大大缓解内容压力, 从而只需要加大磁盘容量, 减少redis的实例数目, 节省了很大的成本. 而key的的通知回调, 时间其实并不敏感, 我们的推送迟个几秒钟, 就算迟发1分钟, 其实也好好. 只要不是不发就行, 于是这个方案目前在成本和可靠性方面, 提供一个最优解.

参考链接

https://www.ibm.com/developerworks/cn/linux/l-cn-timers/index.html
https://aws.amazon.com/sqs/pricing/
https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-send-message-with-timer.html
https://redis.io/topics/notifications
https://docs.keydb.dev/docs/notifications/
https://www.cloudamqp.com/docs/delayed-messages.html
https://wxjiguang.com

本文连接

https://www.wxhmf.com/posts/how-to-push-message-with-timmer-after-user-subscribed-in-wechat-official-account/

如何设计和实现微信公众号关注后48小时内定时给粉丝自动推送客服消息?相关推荐

  1. 如何设置微信公众号关注后自动回复多条图文链接

    对于设置微信公众号关注后自动回复多条图文链接,第三方平台微号帮提供了粉丝关注定时推送功能实现,可以设置微信公众号关注后自动回复多条图文链接,及时帮助公众号激发关注粉丝兴趣,制作需求;可以设置关注延迟推 ...

  2. 微信公众号关注后直接登录网站

    1,获取code 在要实现的地方调用最后的网址,这里需要两项,appid和返回的网址 var appid="{:C('WX_APPID')}"; var back_url=&quo ...

  3. 公众号被关注之后自动回访图文php,如何设置公众号关注后自动回复图文?公众号关注后自动回复有什么用?...

    微信公众号关注后自动回复可以建立用户对你的第一印象,有效活跃用户. 怎样给粉丝同时推送多条消息?怎样给粉丝同时推送文字.图文.图片和小程序消息?这些微信公众后台都做不到,那用什么工具可以实现呢? 答案 ...

  4. 公众号 关注_微信公众号关注图文跳转网页如何操作实现?

    对于微信公众号关注图文跳转网页的场景实现,微号帮平台提供了粉丝关注定时推送功能实现,公众平台提供了开发接口编程实现功能效果,都能实现微信公众号关注图文跳转网页,只要网页能正常在个人微信上打开浏览都能设 ...

  5. 如何获取微信公众号关注页链接

    一:业务场景 有些业务需求需要跳转到公众号的关注页面,不过这种 存在诱导关注的风险,不过下面也介绍一下如何获取. 二:如何获取微信公众号关注页链接? 2.1 思考一下? 想了想是否可以通过下载公众号的 ...

  6. 点击链接跳转到微信公众号关注页、微信关注链接。

    1.获取微信公众号关注页面链接 我是这样获取biz值的:分享一篇该公众号的文章到QQ,然后在QQ里点开这篇文章,打开右上角3个点,复制链接,这个链接里就有biz的值了! 最终拼凑成这样子:[复制到微信 ...

  7. 【无标题】h5跳转微信公众号关注页面

    h5跳转微信公众号关注页面 最近在做h5项目,有个需求是如果用户没有关注公众号,需要引导用户跳转至微信公众号关注页面 制作一个链接,点击该链接跳转到公众号关注页面. [方法一] 1.从公众平台登进入公 ...

  8. 【冷知识】如何快速获取自己的微信公众号关注页的链接地址?

    一:业务场景 目前微信公众号的关注方法基本有三种: 扫描公众号二维码 搜索公众号账号名称 通过阅读公众号发布出来的公众图文,点击上面的微信号名称(右上角三点),可以查看公众号,进入关注页面. 但是如果 ...

  9. 获取微信公众号关注页面链接和历史文章链接

    1.获取微信公众号关注页面链接 我是这样获取biz值的:分享一篇该公众号的文章到QQ,然后在QQ里点开这篇文章,打开右上角3个点,复制链接,这个链接里就有biz的值了! 最终拼凑成这样子:[复制到微信 ...

  10. 微信公众号关注回复多条信息(文字、图片、视频、跳转小程序)

    微信公众号关注回复多条信息(文字.图片.视频.跳转小程序) 对于没做过关注回复多条信息的开发来说,没有实现的思路,花费了一天的时间研究写代码.测试,现做个记录 思路 公众号后台配置关注自动回复只能配置 ...

最新文章

  1. 负载均衡策略_负载均衡策略
  2. Git使用方法——原创
  3. 软件工程 案例分析作业
  4. HomeBrew 安装 国内源
  5. 7-8 判断三角形类型 (20 分)
  6. HTML5缓存和GPS定位
  7. 我的docker随笔17:使用docker-compose启动MySQL、Redis和Mongo
  8. 基于JAVA+Servlet+JSP+MYSQL的停车管理系统
  9. python如何对excel两个单元格求乘积_excel表格怎么求乘积_excel表格多个单元格怎么求积...
  10. Python内置数据结构——字符串string
  11. saltstack的探索-salt指定目标和分组
  12. hadoop发行版本之间的区别
  13. 快速找回Edge浏览器书签的方法
  14. VMware14虚拟机破解版安装详细教程
  15. C# ZPL命令 实现打印中文
  16. 微信公众号工作中如何产生新媒体思维
  17. 5G要来了,实际测试告诉你它的速度到底有多快!
  18. 电容的材质资料/什么cog,x5r y5v等知识
  19. 使用freemarker导出html格式的word(调整页边距,页面视图,正常表格样式)
  20. 基于51单片机的PWM控制马达电机调速正反转(仿真+源码+全套资料)

热门文章

  1. 黑盒测试VS白盒测试
  2. python pysynth随机生成中国风音乐旋律
  3. JAVA发布栅格图层_简单实现栅格布局的两种方式
  4. FFmpeg 软编码H.264与H.265
  5. 记录This request has been blocked; the content must be served over HTTPS.
  6. 使用mbw测试内存带宽性能
  7. TapTap实习两周总结
  8. 使用pandas比对Excel表格,把不同数据列出
  9. 格力电器董事长选举,董明珠当选的可能性极大
  10. 一个专业搬砖人的幻想:全国实现旬休制度