在GAE上使用High Replication Datastore
2011 1 6 12:24 PM 8687次查看
分类:Google App Engine 标签:Google App Engine
和之前使用的Master/Slave方式相比,High Replication提供了更快的响应速度和可用率,但在存储和访问开销上要多于前者,具体差异如下:
- Master/Slave:
采用主从复制系统。写数据时是写入主数据中心,然后再异步复制到从数据中心。读数据时可以选择使用强一致性,但这可能会遇到主数据中心暂时不可用和维护的情况。
不过Google也提供了最终一致性方式来读取,当主数据中心不可用时,可以从从数据中心读取数据。但写数据以及使用事务是不能用最终一致性方式的。 - High Replication:
采用Paxos算法,数据会被同时写入多个数据中心。读写时会有最快的速度,只有当所有数据中心都不可用时才会失败,但不能保证强一致性。
相应的,Google也允许使用实体组来保证强一致性查询,但这需要使用祖先查询。而且如果使用实体组的话,由于实体组不能短时间内被多次更改,因此是无法高效地插入数据的。
Paxos这个算法之前我也研究过,大致上就是一个决策系统,当大多数数据中心认可一个读或写操作后,就认为它有效,因此不会遇到某个数据中心暂时无法访问而失败的情况。(印象中暂时不可用的出现概率是万分之三,懒得去确认了。)
至于开销和速度方面,Google提供了一个比较文档,大多数操作都要花3倍的开销(暂定,7月份可能会更改),而响应时间似乎没有明显提高。
另外,Ikai Lan给出了一个HR query的一致性时间,约为100ms。如果是用Master/Slave,采用最终一致性读取时,同步在大多数情况下(99%+)需要几百ms,但出错时可能需要3~10分钟。
此外,现有的应用都只能使用Master/Slave方式,只有创建新的应用时才能选择High Replication方式。因此Google也提供了一个复制数据的功能,以便你移植到新应用上。
顺带一提,Python SDK 1.4.1也发布了,只是把offline URL Fetch API的时间增加到10分钟而已,这个估计是计划任务或任务队列中的请求时间吧,正常的请求仍然有10秒限制。
更新性能测试:
以2个6字节长的应用来做对比测试,方法是创建、查询、获取和删除500个Test类型无属性的实体,代码如下:
from time import time
from google.appengine.ext import db
class Test(db.Model):
pass
keys = [db.Key.from_path('Test', i) for i in xrange(1, 501)]
tests = [Test(key=key) for key in keys]
t = time()
db.put(tests)
print time() - t
t = time()
Test.all().fetch(500)
print time() - t
t = time()
db.get(keys)
print time() - t
t = time()
db.delete(keys)
print time() - t
测试结果:
Master/Slave:
1.52360796928
0.141813993454
0.147518157959
1.14946293831
ms=3060 cpu_ms=44519 api_cpu_ms=43446 cpm_usd=1.236788
High Replication:
4.77071118355
0.235147953033
3.09301185608
5.15948295593
ms=13304 cpu_ms=114004 api_cpu_ms=112812 cpm_usd=3.166840
由此可见,High Replication在各方面都比Master/Slave慢(特别是db.get(),慢了20倍),而且消耗的资源更多,因此绝大多数应用不建议使用它。
2011年1月7日更新:
Ikai Lan解释了为什么High Replication会慢的原因,以及解决db.get()慢的方法。
- Master/Slave:
向datastore写入数据时,分为2步:- 先写入一个log,这个操作完成后,响应就会返回。
- 接着,后台根据log中的数据,将实体写入实际的datastore。对一个实体组的写入是原子性的。这可以认为是提交步骤。
- 先写入一个log,这个操作完成后,响应就会返回。
- High Replication:
向datastore写入数据时,也是分为2步:- 先写入一个log。为了保证一致性,按照Paxos算法,必须写入大多数(一半以上)数据中心的log。这就是写入延迟会增加的原因。
- 每个数据中心分别根据自己的log来写入datastore。
如果不需要这种强一致性的话,可以进行下面的更改:
经测试,这样修改后,batch get的时间消耗就很接近于fetch了:db.get(keys) #改成: config = db.create_config(deadline=5, read_policy=db.EVENTUAL_CONSISTENCY) db.get(keys, config=config)
5.79944705963
0.194540023804
0.238615989685
5.65248513222
ms=11965 cpu_ms=114077 api_cpu_ms=112812 cpm_usd=3.168863 - 先写入一个log。为了保证一致性,按照Paxos算法,必须写入大多数(一半以上)数据中心的log。这就是写入延迟会增加的原因。
2011年1月8日更新:
Ikai Lan描述了EVENTUAL_CONSISTENCY在Master/Slave方式下的查询情况:先访问master datastore,如果几十ms还未收到响应,再访问slave datastore,然后取它们中最先返回的结果。
2011年7月18日更新:
目前HR和MS的性能已经差不多了:
1.25600385666不过CPU时间仍然要多几倍。
0.146817922592
0.188781023026
1.13988900185
向下滚动可载入更多评论,或者点这里禁止自动加载。