构建高效的EDM平台经验

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: EDM 是 EmailDirect Marketing 的缩写,即邮件营销。是利用电子邮件(Email)与受众客户进行商业交流的一种直销方式,邮件营销对于企业的价值主要体现在三个方面:开拓新客户、维护老客户,以及品牌建设。那么如何才能构建高效的EDM平台经验呢?本文不容错过。

本文是来自中生代技术交流群的分享,本文中京东高级研发工程师刘锟洋将与大家分享构建高效的EDM平台的经验。


1.EDM

EDM 是 EmailDirect Marketing 的缩写,即邮件营销。是利用电子邮件(Email)与受众客户进行商业交流的一种直销方式,邮件营销对于企业的价值主要体现在三个方面:开拓新客户、维护老客户,以及品牌建设。

在互联网领域,大部分企业都有类似业务,国内的比如:京东,当当。国外有Uber,苹果,亚马逊。总体来说,有欧美背景的公司往往比较重视EDM,所以EDM的效果也做得很不错,而国内就相对做的少一点。

京东的EDM应该是其中规模相对大一点的,每日发送量在千万级别,峰值数据2T(每日),如何能在峰值到来时保证系统的稳定,以及从大量的邮件发送任务中筛选出高优先级发送任务并及时发送是构建这个平台的难点。

2.老平台的痛点

在老平台中一封邮件的发送过程大致是这样的:

可以抽象成标准的生产者消费者模型。

数据库作为“生产线”衔接生产平台和发送平台。

这是个过于依赖数据库的设计,生产平台负责插入数据,发送平台负责扫描和处理数据。同一时间内,多个发送平台同时扫表,扫表到数据后更新,更新成功的平台负责执行发送任务。

这个糟糕的设计导致了每次数据库更新操作都只有依靠发送平台数量的成功率,竞争非常激烈。

因为当时对邮件发送服务的经验不足,系统是属于摸着石头过河的方式“长大”的,这直接导致了系统在设计之初缺乏合理的规划和预期,属于无序生长状态,大致表现在:

  1. 类似业务,有完全不同的实现方案。
  2. 应用职责划分不清晰,产生很多鸡肋应用,下线不行,上线难维护。
  3. 应用内部结构紊乱,人为的逻辑复杂。
  4. 实现方案严重依赖数据库,对数据库压力非常大。

当业务需要做出较大变更时,整个EDM平台变成了一块难啃的骨头。

3.新平台的目标

在架构升级改造之初,我们定下了几个目标:

  1. 设计容量至少按现在峰值的三倍设计,针对峰值流量要做到自适应,大促不降级。
  2. 重新梳理应用,必须做到清晰的应用职责划分,不做鸡肋应用。
  3. 应用必须实现任意机房5分钟部署,便于服务的快速搭建和恢复。 

4.新平台的解决方案

第一步是解决“热点”问题。我们做了如下优化:

  1. 物理上,数据库分表,将大表数据隔离。
  2. 按优先级,目标邮箱等条件生成多个Redis FIFO队列,将发送任务预先分流,发送平台到相应队列中获取发送任务并发送。
  3. 集中管理功能,生成新的管理平台,并通过自研的服务监控与配置推送框架时时监控服务,必要时管理员可以在后台通过配置推送干预整个大平台的运行情况。

第二步,提高可用性。我们做了如下优化:

  1. Redis做了一主两从的设计,两个从分布在不同的机房。
  2. 发送平台在多机房部署,保证任何一个机房都可以提供发送服务。
  3. 在MQ消费端,Redis生产端,Redis消费端分别做了阀值控制,从下游到上游,可以依次控制流量在系统内部的流转情况。
  4. 增加Checker,保证邮件发送任务的及时执行。

5.结果

1. 发送效率提升300%(体现在邮件的任务的入库量上)。
2. 在3倍峰值流量下,数据库QPS只有原有数据的1/5,CPU10%以下,load5以下。


6.延展问题

1. 现在的每个元素大约在5K-8K, Redis队列在元素大小大于10K时,性能会急剧下降,如果发送量再大一点,还有哪些办法可以提高Redis的传输效率?
2. 对邮件任务按邮箱分表后,如果是要查询同一个用户的邮箱(用户邮箱一段时间后可能会变),怎么办,有哪几种办法?


Q&A

Q:不明白,分库分表有啥影响?
A:原来所有数据都放在一张表的话,那只要你对这张表进行操作的话,你的页锁,你的表锁都会影响并发的性能。分表后,好处就是并发性更高,坏处就是,如果你用某一个维度进行分表的时候,一旦你用另外一个维度进行查询的时候,就会出现跨表的操作,在某些时候,事务就无法使用了。

Q:分库分表按什么维度来分?
A:当时也考量过几种方案,包括按时间去分,但按时间去分通常有个问题就是,总有一张表是很热的。特别是对这种发送任务,因为我们只需要把任务拿到一个库,发送完毕,更新完毕,这个任务就可以不要了。所以不太适合用按时间分表的方案。

Q:为什么不直接把邮件发送到队列,邮件发送服务再从队列取出发送到目标?
A:其实我们就是这样干的。任务过来后,先到生产平台,然后放到Redis队列中,这是一个先进先出的队列,然后发送平台从这个队列拿到数据后,直接就发送了。

Q:为啥不用NoSQL数据库?
A:有几个原因,第一是因为我们的发送任务是和其他数据是有关联的,有时候是需要事务的存在的,如果用NoSQL,第一事务就没有了,第二,MySQL已能满足目前的需求和能解决问题,所以就没有考虑NoSQL。

Q:只是按邮箱分表吗?处理完的任务怎么处理?
A:发送完成后,拿到发送任务的ID,把任务状态更新为发送完毕就可以了。

Q:既然Redis有10K这样的性能缺陷,换成其他MQ会不会好一些,比如阿里的RocketMQ。
A:其实在京东也MQ中间件,为什么没有选择,是因觉得在这个场景下,如果用了其他的MQ中间件,有时候,如果你用了新的中间件,也会有其他问题引进来。我们觉得MQ中间件对这个场景太重了一点。目前通过Redis队列已能做到了。Redis队列很常用,我们也知道它很稳定。能满足我们的需要。至于说10K这个问题。我们有可能采用的一种方案是,我们在Redis队列里存的数据,只会存一个Key,我们拿到这Key以后,再去Redis队列重新捞一次发送任务,从而把发送任务从Redis队列里解放出来。

Q:那随着时间的推移,每个表的数据量也是急剧增长吧
A:对,这个表会增长得很多,但会定时删除,我们定期每天晚上都会把数据推送到京东的大数据平台上去。数据库只会保留7天之内的数据。

Q:新平台的研发周期有多长
A:比较快,前后大概三个人,一个半月的时间。

Q:到目前为止,有没有遇到一些新的问题?
A:有个点可以和大家分享一下,就是从生产平台到Redis队列这个位置,最开始,我们做的是一个同步,然后单次写到Redis里去,某个任务来了以后,马上入库,往Redis里写,每次推一个5-8K的数据 ,时间消耗大概是几毫秒,但是,等我们改为批量以后,比如我们从原来一次只推一个到现在一次推5个以后,发现它的开销并没有直接指数倍的增长,所以我们在这里把它改为批量加异步的方式,这里有几个好处就是:对业务方来说,只需要等数据入库成功以后,其实接口就已经返回了。所以后台用了一个定时器,批量的把任务合并,批量地往Redis里写,这样性能上增加了百分之二十。



分享者简介

刘锟洋,京东高级研发工程师,3年从事软件研发经验,独立博主,并发编程网编辑。



                                                        中生代技术群微信公众号

                                                da9312524921e637b684eed7bf3249db58f7badc

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
目录
相关文章
|
存储 人工智能 Java
【程序设计】做一个发送系统邮件的功能,如何设计数据表? 转至元数据结尾
重构系统邮件发送旨在实现统一的邮件发送功能,通过公共API提供服务。设计包括两个核心数据表:`mail` 表用于存储邮件基本信息,如邮件ID、业务类型、发送者、标题、内容、附件信息、发送状态和时间戳;`mail_receiver` 表记录邮件接收者信息,包括邮件ID、接收者邮箱、接收者类型、发送状态和重试次数。为了优化查询性能,建议创建`Email_Content`表,将`content`和`attach_file`从`Email`表中分离,以减少主表大小。这有助于提高主表的查询速度,并通过定期的数据结转策略,确保热表只存储最近的数据。
260 0
|
Java
JVM深入学习(十八)-如何查询当前jvm使用的垃圾回收器
如何查看使用的jdk用的垃圾回收器类型?
1097 0
|
9月前
|
搜索推荐 数据挖掘 双11
淘宝运营进阶秘籍:从业余到专业
淘宝运营涉及市场分析、产品定位、店铺装修、营销推广、客户服务、数据分析等多环节。要脱颖而出,需掌握进阶秘籍。本文从精准定位、店铺装修、定价策略、流量获取、客户服务、数据分析及跨平台合作七大方面深入探讨,助商家实现从平凡到卓越的蜕变。通过目标受众分析、优化店铺形象、合理定价、多种促销手段、提升客户体验、利用数据反馈调整策略以及拓展销售渠道,商家可逐步提升运营能力,在竞争激烈的电商环境中取得成功。
1189 4
|
数据可视化 数据挖掘 定位技术
在服务中收集和测试数据
【6月更文挑战第16天】本文讨论了数据收集和测试的重要性,指出样本量应根据时间和预算调整。数据分析涉及比较结果与假设,可视化数据以增强理解,并通过统计测试确认显著性。设计的持续优化是关键,适应变化的业务、技术和用户需求,数据驱动的方法能提供最佳用户体验。
164 5
在服务中收集和测试数据
|
数据采集 自然语言处理 关系型数据库
在 MySQL 中使用 REPEAT
【8月更文挑战第6天】
502 0
在 MySQL 中使用 REPEAT
VSCode将某个字符替换为换行符并换行显示
VSCode将某个字符替换为换行符并换行显示
1120 1
VSCode将某个字符替换为换行符并换行显示
java.lang.NoClassDefFoundError: com/sun/jna/Callback
java.lang.NoClassDefFoundError: com/sun/jna/Callback
191 0
|
iOS开发 开发者
iOS 分发证书过期或手动吊销,会影响 App 的下架吗?
iOS 分发证书过期或手动吊销,会影响 App 的下架吗?
|
IDE Java Maven
IDEA 一键生成 Maven 依赖关系图,太强大了。。
IDEA 一键生成 Maven 依赖关系图,太强大了。。
772 0
IDEA 一键生成 Maven 依赖关系图,太强大了。。
|
机器学习/深度学习 资源调度 算法
推荐系统[三]:粗排算法常用模型汇总(集合选择和精准预估),技术发展历史(向量內积,Wide&Deep等模型)以及前沿技术
推荐可分为以下四个流程,分别是召回、粗排、精排以及重排: 1. 召回是源头,在某种意义上决定着整个推荐的天花板; 2. 粗排是初筛,一般不会上复杂模型; 3. 精排是整个推荐环节的重中之重,在特征和模型上都会做的比较复杂; 4. 重排,一般是做打散或满足业务运营的特定强插需求,同样不会使用复杂模型;
推荐系统[三]:粗排算法常用模型汇总(集合选择和精准预估),技术发展历史(向量內积,Wide&Deep等模型)以及前沿技术

热门文章

最新文章