数据偏移、分区陷阱……我们这样避开DynamoDB的5个坑

摘要:本文主要介绍作者所在团队在具体业务中所遇到的挑战,基于这些挑战为何最终选型使用Amazon DynamoDB,在实践中遇到了哪些问题以及又是如何解决的。文中不会详细讨论Amazon DynamoDB的技术细节,也不会涵盖Amazon DynamoDB的全部特性。

DynamoDB是Amazon基于《Dynamo: Amazon’s Highly Available Key-value Store》实现的NoSQL数据库服务。它可以满足数据库无缝的扩展,可以保证数据的持久性以及高可用性。开发人员不必费心关注DynamoDB的维护、扩展、性能等一系列问题,它由Amazon完全托管,开发人员可以将更多的精力放到架构和业务层面上。

背景与挑战

TalkingData移动广告效果监测产品(TalkingData Ad Tracking)作为广告主与媒体之间的一个广告投放监测平台,每天需要接收大量的推广样本信息和实际效果信息,并最终将实际的效果归因到推广样本上。

举个例子,我们通过手机某新闻类APP浏览信息,会在信息流中看到穿插的广告,广告可能是文字形式、图片形式、视频形式的,而不管是哪种形式的广告它们都是可以和用户交互的。

如果广告推送比较精准,刚好是用户感兴趣的内容,用户可能会去点击这个广告来了解更多的信息。一旦点击了广告,监测平台会收到这一次用户触发的点击事件,我们将这个点击事件携带的所有信息称为样本信息,其中可能包含点击的广告来源、点击广告的时间等等。通常,点击了广告后会引导用户进行相关操作,比如下载广告推荐的APP,当用户下载并打开APP后,移动广告监测平台会收到这个APP发来的效果信息。到此为止,对于广告投放来说就算做一次成功转化。

移动广告监测平台需要接收源源不断的样本信息和效果信息,并反复、不停的实时处理一次又一次转化。对于监测平台来讲,它的责任重大,不能多记录,也不能少记录,如果转化数据记多了广告主需要多付广告费给媒体,记少了媒体会有亏损。这样就为平台带来了几大挑战:

  • 数据量大

有的媒体为了利益最大化可能会采取非正常手段制造假的样本,产生“虚假流量”,所以广告监测平台除了会收到真实用户样本外,也会收到大量造假的样本,影响正常的监测和归因。在最“疯狂”的时候,我们的平台会在一天内收到40亿+的点击样本事件请求。要知道,这些点击样本事件是要保留下来作为后续效果归因用的,而且样本有效期大不相同,从最短12小时到最长90天不等。

  • 数据量不可预知

对于广告主的大推、应用商店竞价排名等一系列的推广,会导致突发大量样本数据流入。面对这些流量不可预知的情况,我们仍要保证系统的正确、稳定、实时。

  • 实时处理

广告主依赖广告监测平台实时处理的结果来调整广告推广策略。因此广告监测平台需要支持数据实时处理,才能为广告主更快的优化推广策略提供有力支撑。与此同时,广告监测平台的处理结果也要实时回传给媒体方以及广告主。可以看到,准确性和实时性是系统必须要满足的基本条件。

  • 样本存储

我们的业务最核心的功能就是归因,我们要明确例如用户下载打开APP的这个转化效果是由哪一个推广活动样本带来的——也就是上图中的第7步,当用户安装APP后,监测平台要对应找到第1步中样本所在推广活动,这个是一个查询匹配的过程。

对于庞大的归因样本数据,有效期又各不相同,我们应该怎样存储样本才能让系统快速归因,不影响实时结果,这也是一个很大的挑战。

最初形态 

在2017年6月前我们的业务处理服务部署在机房,使用Redis Version 2.8存储所有样本数据。Redis使用多节点分区,每个分区以主从方式部署。在最开始我们Redis部署了多个节点,分成多个分区,每个分区一主一从。刚开始这种方式还没有出现什么问题,但随着用户设置的样本有效期加长、监测样本增多,当时的节点数量逐渐已经不够支撑业务存储量级了。如果用户监测推广量一旦暴增,我们系统存储将面临崩溃,业务也会瘫痪。于是我们进行了第一次扩容。

由于之前的部署方式我们只能将Redis的多个节点翻倍扩容,这一切都需要人为手动操作,并且在此期间我们想尽各种办法来保护用户的样本数据。

这种部署方式随着监测量的增长以及用户设定有效期变长会越来越不堪重负,当出现不可预知的突发量时就会产生严重的后果。而且,手动扩容的方式容易出错,及时性低,成本也是翻倍的增长。在当时由于机器资源有限,不仅Redis需要扩容,广告监测平台的一系列服务和集群也需要进行扩容。

化解挑战

经过讨论和评估,我们决定将样本处理等服务迁移到云端处理,同时对存储方式重新选型为Amazon DynamoDB,它能够满足我们的绝大部分业务需求。经过结构调整后系统大概是下图的样子:

  • 应对数据量大且不可预知

我们的平台需要接受推广监测连接请求,并进行持久化用于后续的数据归因处理。理论上来说系统进来多少广告监测数据请求,DynamoDB就能存多少数据,只需要一张表就可以存储任意数量级的数据。不用关心DynamoDB扩容问题,在系统运行时我们感知不到存储正在扩容。这也是Amazon官方宣称的完全托管、无缝扩展。

  • 高可用

Amazon DynamoDB作为存储服务提供了极高的可用性,对于写入DynamoDB的全部数据都会存储到固态硬盘中,并且自动同步到AWS多个可用区,以达到数据的高可用。这些工作同样完全由Amazon DynamoDB服务托管,使用者可以将精力放到业务架构及编码上。

  • 实时处理

Amazon DynamoDB提供了极高的吞吐性能,并且支持按秒维度配置任意级别的吞吐量。对于写多读少的应用可以将每秒写入数据的数量调整成1000甚至更高,将每秒读取的数量降低到10甚至更少。

吞吐量支持使用者任意设定,在设定吞吐量时除了可以随时在Web管理后台调整外,还可以通过DynamoDB提供的客户端动态调整。比如系统在运行时写入能力不足了,我们可以选择到Web管理后台手动上调或在代码中通过调用客户端API的方式实现自动上调。使用客户端动态调整的方式会让系统具备较高的收缩能力,同时还可以保证数据的实时处理,系统数据流量变高了就动态调整上去,数据流量变低了再动态调整下来。相比手动调整来看,动态调整的方式更为灵活。

基于以上几点,我们认为Amazon DynamoDB可以很轻松的支撑系统的核心业务能力。对于业务侧需要做的就是,整理好业务逻辑把数据写到DynamoDB就可以了,剩下的就交给DynamoDB去做。

此外还有:

  • TTL

我们利用了Amazon DynamoDB提供的TTL特性管理那些有生命周期的数据。TTL是对表中要过期的数据设置特定时间戳的一种机制,一旦时间戳过期DynamoDB在后台会删除过期的数据,类似于Redis中的TTL概念。借助TTL的能力,我们减少了很多业务上不必要的逻辑判定,同时还降低了因存储量带来的成本。

在我们的业务中没有启用流来捕获表的动作,但我们认为DynamoDB流是一个非常好的特性,当存储在DynamoDB表中的数据发生变更(新增、修改、删除)时,通知到相关的服务/程序。比如我们修改了一条记录的某个字段,DynamoDB可以捕获到这个字段的变更,并将变更前后的结果编写成一条流记录。

实践出真知

我们在使用一些开源框架或服务时总会遇到一些“坑”,这些“坑”其实也可以理解为没有很好的理解和应对它们的一些使用规则。DynamoDB和所有服务一样,也有着它自己的使用规则。在这里主要分享我们在实际使用过程中遇到的问题以及解决办法。

数据偏移 

在DynamoDB中创建表时需要指定表的主键,这主要为了数据的唯一性、能够快速索引、增加并行度。主键有两种类型,「单独使用分区键」作为主键和「使用分区键+排序键」作为主键,后者可以理解为组合主键(索引),它由两个字段唯一确定/检索一条数据。DynamoDB底层根据主键的值对数据进行分区存储,这样可以负载均衡,减轻单独分区压力,同时DynamoDB也会对主键值尝试做“合理的”分区。

在开始我们没有对主键值做任何处理,因为DynamoDB会将分区键值作为内部散列函数的输入,其输出会决定数据存储到具体的分区。但随着运行,我们发现数据开始出现写入偏移了,而且非常严重,带来的后果就是导致DynamoDB表的读写性能下降,具体原因在后面会做详细讨论。发现这类问题之后,我们考虑了两种解决办法:

解决办法 优点 缺点
对写入数据主键值追加随机数,将数据打散 能降低数据严重偏移 由于主键随机性,我们将无法根据主键查询,因此也失去了读性能
对写入数据主键值做哈希 能降低数据严重偏移、哈希规则相同,可使用主键查询 好像没什么缺点

所以我们选择了第二种方法,调整业务代码,在写入时将主键值做哈希,查询时将主键条件做哈希进行查询。

自动扩容潜规则 

在解决了数据偏移之后读/写性能恢复了,但是运行了一段时间之后读写性能却再次下降。查询了数据写入并不偏移,当时我们将写入性能提升到了6万+/秒,但没起到任何作用,实际写入速度也就在2万+/秒。最后发现是我们的分区数量太多了,DynamoDB在后台自动维护的分区数量已经达到了200+个,严重影响了DynamoDB表的读写性能。

DynamoDB自动扩容、支持用户任意设定的吞吐量,这些都是基于它的两个自动扩容规则:单分区大小限制和读写性能限制。

单分区大小限制 

DynamoDB会自动维护数据存储分区,但每个分区大小上限为10GB,一旦超过该限制会导致DynamoDB拆分区。这也正是数据偏移带来的影响,当数据严重偏移时,DynamoDB会默默为你的偏移分区拆分区。我们可以根据下面的公式计算分区数量:

数据总大小 / 10GB 再向上取整 = 分区总数

比如表里数据总量为15GB,15 / 10 = 1.5,向上取整 = 2,分区数为2,如果数据不偏移均匀分配的话两个分区每个存储7.5GB数据。

读写性能限制 

DynamoDB为什么要拆分区呢?因为它要保证用户预设的读/写性能。怎么保证呢?依靠将每个分区数据控制在10G以内。另一个条件就是当分区不能满足预设吞吐量时,DynamoDB也会将分区进行扩充。DynamoDB对于每个分区读写容量定义如下:

  • 写入容量单位

写入容量单位(WCU:write capacity units),以每条数据最大1KB计算,最大每秒写入1000条。

  • 读取容量单位

读取容量单位(RCU:read capacity units),以每条数据最大4KB计算,最大每秒读取3000条。

也就是说,一个分区的最大写入容量单位和读取容量单位是固定的,超过了分区最大容量单位就会拆分区。因此我们可以根据下面的公式计算分区数量:

(预设读容量/3000)+(预设写容量/1000)再向上取整 = 分区总数

比如预设的读取容量为500,写入容量为5000,(500 / 3000) + (5000 / 1000) = 5.1,再向上取整 = 6,分区数为6。

需要注意的是,对于单分区超过10G拆分后的新分区是共享原分区读写容量的,并不是每个表单独的读写容量。

因为预设的读写容量决定了分区数量,但由于单分区数据量达到上限而拆出两个新的分区。

所以当数据偏移严重时,读写性能会急剧下降。

冷热数据 

产生上面的问题是由于我们一开始是单表操作。这样就算数据不偏移,但随着时间推移数据量越来越多,自然拆出的分区也越来越多。

因此,我们根据业务做了合理的拆表、设定了冷热数据表。这样做有两大好处:

  1. 提升性能

这一点根据上面的规则显而易见,热表中数据量不会持续无限增长,因此分区也稳定在一定数量级内,保证了读写性能。

  • 降低成本

无谓的为单表增加读写性能不仅效果不明显,而且费用也会急剧增高,使用成本的增加对于谁都是无法接受的。DynamoDB存储也是需要成本的,所以可以将冷表数据存储到S3或其他持久化服务中,将DynamoDB的表删除,也是降低成本的一种方式。

表限制 

表对于数据的大小以及数量并没有限制,可以无限制的往一张表里写入数据。但对于AWS的一个账户,每个DynamoDB使用区域的限制为256张表。对于一个公司来说,如果共用同一个账号的话可能会存在创建表受限的风险。所以如果启用了冷热表策略,除了删冷表降低成本外,也是对256张表限制的一种解决办法。

属性名长度 

上面提到了写入单位每条数据最大1KB、读取单位每条最大4KB的限制。单条数据的大小除了字段值占用字节外,属性名也会占用字节,因此在保证可读性的前提下应尽量缩减表中的属性名。

总结

DynamoDB的使用也是存在成本的,主要体现在写入和读取的费用。我们自己研发了一套按照实际流量实时调整读、写上限的策略。随着发展DynamoDB也推出了Auto Scaling功能,它实现了自定义策略动态调整写入与读取上限的能力,对于开发者来说又可以省去了不少研发精力。目前我们也有部分业务使用了Auto Scaling功能,但由于该功能的限制,实际使用上动态调整的实时性略显欠缺。

作者简介:

史天舒,资深Java工程师,硕士毕业于北京邮电大学。任职于TalkingData,目前从事移动广告监测产品Ad Tracking相关架构设计与开发。喜欢研究代码,注重系统高扩展设计,略有代码洁癖。

Image placeholder
PlatozzZ
未设置
  46人点赞

没有讨论,发表一下自己的看法吧

推荐文章
智能数据可视化的5个步骤

如今,许多企业正在利用模型、数据分析、数据可视化和仪表板等措施实现数据驱动。例如商业领袖注重提升客户体验,技术领导者注重分析速度和网站指标,应用程序团队在其应用程序中嵌入分析程序等等。这意味着更多的开

关于企业数字化转型和AI应用的5个建议

波士顿咨询公司(BostonConsultingGroup)表示,企业对数字化转型和人工智能抱有很高的期望,但也面临着一些挑战。许多企业正在迎来第一波数字化转型浪潮,在扩大覆盖面和定制化、改进流程、提

对2020年Linux和开源的5个大胆预测

在这篇文章中,omgubuntu网站列出了对2020年Linux的5个预测,大家也来预测下会不会实现。2020年Linux预测预测1:Linux设备的爆炸式增长好的,因此建议我们明年看到大量新的Lin

企业应如何进行云迁移?小心这5个陷阱!

  国际数据公司(InternationalDataCorp)表示,到2022年,全球数字化转型支出将达到近2万亿美元。然而,各种各样的迁移事故仍然会对企业数字化转型过程造成阻碍,威胁着企业的生存与发

分布式时序数据库QTSDB的设计与实现

现有的开源时序数据库influxdb只支持单机运行,在面临大量数据写入时,会出现查询慢,机器负载高,单机容量的限制。为了解决这一问题,360基础架构团队在单机influxdb的基础上,开发了集群版——

PingCAP马晓宇:TiDB的HTAP之路

HTAP是目前数据库领域比较热门的一个概念,它既能支持OLTP(在线事务处理),又能支持OLAP(在线分析处理),可以涵盖大部分企业级应用的需求,一站式解决他们的问题。本次,小编有幸采访到PingCA

在头条和百度搜索了100个关键词之后,我们发现……

作者|闫丽娇苏琦编辑|苏琦• 常用名词搜索方面,百度站外内容占比更高,内容来源比头条更多元。头条搜索的信息流广告目前还没有接入;• 疑问解答类搜索,百度的内容发散性更杂,而头条在信息准确度上更能理解用

记一次JVM FullGC引发严重线上事故的定位、分析、解决过程!

这篇文章给大家聊一次线上生产系统事故的解决经历,其背后代表的是线上生产系统的JVMFullGC可能引发的严重故障。一、业务场景介绍先简单说说线上生产系统的一个背景,因为仅仅是文章作为案例来讲,所以弱化

关于网络安全防御,每个中小企业应该知道的5件事

根据美国商业促进局(BBB)的数据显示,你可能会惊讶地发现,小型企业占北美所有企业的97%以上。根据这个统计数字,我认为好消息是,在所有网络攻击中,针对小企业的攻击不到一半。坏消息是,当中小企业受到攻

超8千Star,火遍Github的Python反直觉案例集!

大数据文摘授权转载作者:SatwikKansal译者:暮晨Python,是一个设计优美的解释型高级语言,它提供了很多能让程序员感到舒适的功能特性。但有的时候,Python的一些输出结果对于初学者来说似

CentOS7 下使用 rsync+sersync 配置文件自动同步

为什么需要文件自动同步功能? 我们平时上传代码,可以通过ftp、sftp等将文件上传至服务器,耗时耗力,而且很容易出错。如果服务器数量少还好,一但服务器数量增加,压力可想而知。 这个时候我们可以使用各

Rust 标准库中的 async/await (async-std)

Rust对齐标准库中的async/await(async-std)简介现在的rust生态中,async/await在rust1.39中已经stable,其他库还有futures已经到0.3.x,还有就

做机器学习项目数据不够?这里有5个不错的解决办法

许多开展人工智能项目的公司都具有出色的业务理念,但是当企业AI团队发现自己没有足够多的数据时,就会慢慢变得十分沮丧……不过,这个问题的解决方案还是有的。本文将简要介绍其中一些经笔者实践证明确实有效的办

干了5年程序员,该如何转行?5个新工作方向了解一下

大数据文摘出品来源:Medium编译:灿灿、曹培信写了5年代码,年龄已近30,头发尚存几缕,除了写代码其他并无所长,职业未来在何方?对于从毕业就进入互联网公司,已经工作了5年甚至更久的程序员来说,现在

Docker最佳实践:5个方法精简镜像

本文记录了精简Docker镜像尺寸的必要性及好处精简Docker镜像的好处很多,不仅可以节省存储空间和带宽,还能减少安全隐患。优化镜像大小的手段多种多样,因服务所使用的基础开发语言不同而有差异。本文将

敏捷开发流程之Scrum:3个角色、5个会议、12原则

本文主要从Scrum的定义和目的、敏捷宣言、Scrum中的人员角色、Scrum开发流程、敏捷的12原则等几方面帮助大家理解Scrum敏捷开发的全过程。一、Scrum的定义和目的Scrum是一个用于开发

MongoDB数据库因安全漏洞,导致Family Locator泄露二十多万名用户数据

摘要:本月第二次,未受保护的MongoDB数据库因大量安全漏洞而导致敏感信息泄露,受欢迎的家庭跟踪应用程序FamilyLocator已经暴露了超过238,000名用户的实时未加密位置数据。该应用程序非

甲骨文裁员,N+6 赔偿……部分员工不满

本文转自|猿记据多家媒体昨日报道,5月7日上午甲骨文召开了面向全中国区的电话会议,亚太区人力资源负责人在会上简要介绍道,公司正进行业务结构调整,导致一部分人要离开岗位,这将是全球性的。据悉,此次主要裁

看完秒变5G专家!关于5G,你必须知道的事儿……

本文转自|鲜枣课堂   什么是5G    5G,就是5thGenerationMobileNetworks(第五代移动通信网络),也可以称为5thGenerationWirelessSystems(第

黑客锁定市政系统勒索比特币,政府拒付赎金!全美最危险城市陷入瘫痪的第三周……

大数据文摘出品作者:李雷、狗小白、宋欣仪政府邮箱无法访问、所有水电费停车费无法缴纳、所有房产交易无法进行。在美国东部城市巴尔的摩市,这样的市政系统瘫痪已经持续了三周。5月初,黑客入侵并控制了美国马里兰

太丢人了……GitHub 阿波罗11号代码仓库惨遭中文灌水

近日登上GitHub趋势热榜第一的阿波罗11号(Apollo11)代码仓库,获得了3万多标星称赞,但也同时惨遭中文灌水的侵扰,引发了众多网友的热议。50年前,三位宇航员搭乘阿波罗11号,完成人类第一次

学习 nodejs+mongodb+koa2 写接口(一) 环境布置

一.环境准备最近在学用Nodejs写后端接口,了解到koa2是Nodejs的一个框架。可以快速开发后端接口,同时也能更快熟悉Nodejs以下是所需的环境node  v7.6+,可以用nvm或者n安装指

学习 nodejs+mongodb+koa2 写接口(二) koa2教程入门

一.hellokoa安装koa2#初始化package.json npminit #安装koa2 npminstallkoahelloworld代码constKoa=require('koa') c

快看,我们的分布式缓存就是这样把注册中心搞崩塌

写公众号两年以来,每当有机会写故障类主题的时候,我都会在开始前静静地望着显示器很久,经过多次煎熬和挣扎之后才敢提起笔来,为什么呢?因为这样的话题很容易招来吐槽,比如“说了半天,不就是配置没配好吗?”,

MongoDB与阿里云达成战略合作,云将是数据库最佳载体

摘要:开源数据库厂商与云服务供应商两大阵营之间存在争议是事实,MongoDB与阿里云达成战略合作,背后意味着什么?对MongoDB,对阿里云分别意味着什么?对整个数据库产业又意味着什么?MongoDB