亚马逊AWS官方博客

DAX – DynamoDB集成全托管的内存缓存,轻松搞定读取负载!

相信大家已经都知道,Amazon DynamoDB 是一项全托管的NoSQL 数据库服务,适合所有需要一致性且延迟低于 10 毫秒的任意规模的应用程序,支持文档和键值存储模型。使用DynamoDB,可创建数据库表来存储和检索任意量级的数据,并提供任意级别的请求流量。现在,DynamoDB还提供了Auto-Scaling的功能,即可以通过你预先设置的阈值自动扩展和缩减表的吞吐量,做到完全弹性自动伸缩的目的,真正达到让你的数据库按实际吞吐量进行付费。

这么高的并发量却依然可以保持服务器的平均延迟在个位数毫秒,这让DynamoDB受到了非常多用户的青睐。然而随着大数据时代的数据暴增,很多客户的场景比较特殊,他们对数据库的响应时间越来越苛刻,甚至需要达到微秒的级别!这无疑给DynamoDB数据库又带来了一个难题。甚至也有客户会提到,能不能在DynamoDB前面放一层类似Redis的Cache服务呢?如果这样做的话,需要自己搭建缓存数据库,并且解决DynamoDB和Redis之间的数据同步问题;同时还要重写代码实现业务逻辑,比如如果数据在缓存中,则立即返回,如果数据没有在缓存中,则必须从数据库里面读取,将数据写入到缓存中,然后再返回。

当用户还带着这样的担心时,现在,Amazon DynamoDB已经整合了这一特性,推出了一个新的功能,即Amazon DynamoDB Accelerator,简称DAX。这是一种完全托管并且高度可靠的内存缓存,即使每秒种的请求量达到数百万,却依然可以将Amazon DynamoDB的响应时间从数毫秒缩短到数微秒!其实在很多场景都可以用到DAX,比如实时竞拍、秒杀、电商、社交游戏等场景,DAX可以提供快速的内存读取性能;再比如在产品促销日,读取访问量会明显上升,但是销售日结束访问量就会回归正常,诸如此类读取密集型的工作负载但同时又对成本敏感的应用都可以使用DAX服务。像类似于Expedia、Twilio、Genesys、eyeview等客户都已经率先用上了DAX服务

目前,DAX还是处于预览版,您可以点击链接进行申请。接下来,让我们创建一个DAX集群,赶紧体验一下微秒级别的响应测试吧!

1. DAX集群的原理

上图中可以看到,DAX起了一组缓存的节点(目前最多可以是10个节点),并将这些节点置放在VPC内部,应用程序部署在EC2上,这样EC2和DAX Cluster通过内网直接访问。关于DAX的内存缓存,主要是DynamoDB的读和写操作:

(1)最终一致性的读取操作,支持GetItem、BatchGetItem、Query、Scan接口,如果读取在DAX缓存中命中,将直接从DAX集群里读取;如果是第一次读取没有命中,那就从DyanmoDB里面读取。

(2)写入操作支持BatchWriteItem、UpdateItem、DeleteItem、PutItem接口,写入的时候数据先写入到DynamoDB表,确认写入成功之后,然后再写到DAX集群(item cache),这个操作只有在DynamoDB表和DAX集群都写入了数据的时候才算成功。如果由于一些原因这个操作失败了,那么这个item将不会缓存到DAX里面,并且会抛出一个exception。这种方式可以让缓存和数据库的数据保持一致性和完整性,不会出现过期数据在缓存里面。

(3)如果DAX有多个节点时,会选取一个主节点(primary node),多个从节点(read replica node),数据最终会分布到所有节点上,但对于客户端来说,只需要关心唯一的DAX连接地址,已经内置了负载均衡和路由策略,并且自动执行故障检测、故障恢复、软件修补等管理任务。

接下去,我们将模拟这一过程,进行实际测试。

2. 启动DAX集群

首先启动一个DAX集群,指定集群的节点数(目前节点最多为10个),我们建议您在生产环节中启用两个以上的节点,并将这些节点置放在不同的可用区中,从而提高高可用。设置好相应的IAM Role和Policy。Policy可以配置“只读”权限,或者“读和写”权限。更多关于权限配置可以参考:

http://s3.amazonaws.com/dynamodb-preview-dax/DAX.access-control.html

接下去设置DAX集群的子网组,DAX集群的节点会部署在这些子网里面。选定VPC和相对应的子网,并设置安全组。安全组入站需要打开DAX所用到的8111端口。

接下去配置DAX的参数组,指定Cache的Query TTL和Item TTL值。TTL的时间小到可以是“秒”,大到可以到“天”。

也可以自定义选定维护窗口,如果需要的话可以再加一个SNS通知,这样只要集群有维护就会立刻以短信,或者邮件等形式通知到您。

到这里,DAX集群就创建成功了。DAX集群会有一个唯一的endpoint地址,例如,这里是

dax-cluster-demo.bnsilv.clustercfg.dax.usw2.cache.amazonaws.com:8111

另外可以看到在这个例子中DAX集群启动了3个节点。

DAX集群具体的3个节点

3. 启动EC2 ,作为应用程序的server,同时作为DAX的client

如果仅作为测试,可以启动一台t2.micro的小型机器(Amazon Linux)。

EC2通过监控检查,启动成功。

4. 安装Java应用程序

(1)首先通过客户端连接到这台Amazon Linux EC2

(2)安装Java SDK

sudo yum install -y java-devel

(3)下载最新版的AWS Java SDK

wget https://s3-us-west-2.amazonaws.com/danrongdemo/DynamoDB-Accelerator-Test-Demo/aws-java-sdk-1.11.125.zip

unzip aws-java-sdk.zip

(4)下载最新版的DAX Jave客户端

wget https://s3-us-west-2.amazonaws.com/danrongdemo/DynamoDB-Accelerator-Test-Demo/DaxJavaClient-latest.jar

(5)设置CLASSPATH环境变量

export SDKVERSION=1.11.125

export CLASSPATH=.:./DaxJavaClient-latest.jar:aws-

java-sdk-$SDKVERSION/lib/aws-java-sdk-$SDKVERSION.jar:aws-

java-sdk-$SDKVERSION/third-party/lib/*

(6)下载Java应用程序代码

wget https://s3-us-west-2.amazonaws.com/danrongdemo/DynamoDB-Accelerator-Test-Demo/TryDax.zip

unzip TryDax.zip

(7)编译代码:javac TryDax*.java

(8)执行代码:java TryDax

以下是完整的应用程序拓扑图

5. 直接读取DynamoDB表的响应测试

从图中可以看到,直接从DynamoDB表里进行读取数据,分布执行了GetItem、Query、Scan操作,服务器的平均延时在个位数毫秒级别(小于10ms)。

此时查看DAX的监控还没有任何cache指标产生:

6. 加上DAX后进行测试

调整DAX的endpoint,通过代码判断当daxClient不为空时,就会采用DAX方式去查询。

将DAX的endpoint以参数形式传入执行,代码会判断DynamoDB的读取操作启用DAX内存缓存。

再次执行查询操作,发现:

上图中可以发现,第一次通过GetItem读取的时候由于DAX集群中没有数据,所以直接读取DynamoDB表,延迟在4.7ms左右,与此同时,会把数据写入到DAX集群中。当再次进行GetItem读取的时候,会直接从DAX内存缓存中读取,响应时间大概在0.8ms左右。同理,对于Query操作也可以发现,第一次查询DynamoDB表的响应时间是17.2ms,但是第二次读取时直接从DAX进行查询,响应时间缩短到了0.5ms左右。因此,不管是GetItem,Query还是Scan操作,读取操作的响应时间都已经大大提升了!另外,对于读取和写入操作,DAX已经自动集成了CloudWatch进行监控,很容易可以监控例如CPU使用率,Item Cache命中数,Query Cache命中数,总共的请求数等19个指标。

7. 如何将DAX整合到现有的DyanmoDB开发中?

您有可能会关心,我现在的业务代码已经基于DynamoDB开发好了,如何要把DAX整合进去,代码的开动量会不会很大呢?这一问题AWS已经替您考虑到了,例如有一张名为Music的表,主键(partition key)是Artist,排序建(sort key)是SongTitle。直接上代码:

8. 如何增加DAX的集群节点数?

增加DAX的节点数,可以通过API或者命令行操作,点击“Add node”:

然后选择新增加节点的个数,可以自定义DAX节点所在的可用区。如下:

9. 小结

如果您已经在使用Amazon DynamoDB了,集成DAX只需要稍微改动一下DAX client的实现,核心的业务逻辑代码基本上不用做任何改动。

DynamoDB的服务器平均延时在个位数毫秒级别,但是新出的DAX功能和DyanmoDB配合起来使用,则可以性能进一步推到一个新的层级,在处理每秒接收数以百万计请求的读取密集型工作负载时,响应时间缩短到以微秒级别,大概在0.几个ms左右。效果还是蛮惊人的!

更多DAX的介绍: https://aws.amazon.com/cn/dynamodb/dax/

关于DAX的价格: https://aws.amazon.com/cn/dynamodb/pricing/

作者介绍

毛郸榕

AWS解决方案架构师,负责基于AWS的云计算方案架构的咨询和设计,同时致力于AWS云服务在国内的应用和推广,毕业于北京航空航天大学云计算专业,硕士,毕业后直接加入亚马逊AWS中国。在大规模后台架构、企业混合IT和自动化运维等方面有着丰富的实践经验。目前在集中精力学习新一代无服务器架构的开发与设计。