Chr*_*row 13 java google-app-engine database-design bigtable denormalization
我正在使用谷歌应用引擎(GAE)进行Java.我正在努力设计一个能够发挥大表优势和劣势的数据模型,这些是之前的两个相关帖子:
我暂时决定在一个完全规范化的主干上,将非规范化属性添加到实体中,这样大多数客户端请求只能用一个查询来处理.
我认为完全规范化的主干将:
而非规范化数据将:
我观看了一个app引擎视频,描述了一种被称为"扇出"的技术.我们的想法是快速写入规范化数据,然后使用任务队列完成幕后的非规范化,而无需客户端等待.我已将视频添加到此处以供参考,但它只需一小时,而且无需观看它就能理解这个问题:http: //code.google.com/events/io/2010/sessions/high-throughput -data-管道,appengine.html
如果我使用这种"扇出"技术,每次客户端修改一些数据时,应用程序将在一次快速写入中更新规范化模型,然后将非规范化指令发送到任务队列,这样客户端就不必等待他们也完成了.
使用任务队列更新数据的非规范化版本的问题在于,在任务队列完成对该数据的非规范化之前,客户端可以对刚刚修改的数据发出读取请求.这将为客户端提供过时的数据,这些数据与他们最近的请求混淆客户端并使应用程序显得有问题.
作为补救措施,我建议通过URLFetch异步调用应用程序中的其他URL来并行扇出非规范化操作:http://code.google.com/appengine/docs/java/urlfetch/ 应用程序将等到所有在响应客户端请求之前已完成异步调用.
例如,如果我有一个"约会"实体和一个"客户"实体.每个约会将包括其预定的客户信息的非规范化副本.如果客户更改了他们的名字,那么该应用程序将进行30次异步调用; 每个受影响的约会资源一个,以便更改每个客户的名字副本.
从理论上讲,这可以全部并行完成.所有这些信息都可以在大约花费1或2次写入数据存储区所需的时间内更新.在非规范化完成后,可以对客户端做出及时响应,消除客户端暴露于不一致数据的可能性.
我看到的最大的潜在问题是,应用程序在任何时候都不能有超过10个异步请求调用(此处记录):http://code.google.com/appengine/docs/java/urlfetch/overview .html).
我提出的补救措施是将非规范化指令发送到另一个资源,该资源递归地将指令拆分成相等大小的较小块,用较小的块作为参数调用自身,直到每个块中的指令数足够小以便完全执行.例如,如果具有30个关联约会的客户更改了其名字的拼写.我将使用指令更新所有30个约会来调用非规范化资源.然后,它将这些指令分成10组3条指令,并使用每组3条指令向其自己的URL发出10个异步请求.一旦指令集小于10,资源就会根据每条指令直接发出异步请求.
我对这种方法的担忧是:
我真的很感激这种方法的一些意见.
这听起来非常复杂,设计越复杂,编码和维护就越困难。
假设您需要对数据进行非规范化,我建议仅使用基本的非规范化技术,但要跟踪正在更新的对象。如果客户端请求一个正在更新的对象,你知道你需要查询数据库来获取更新的数据;如果没有,您可以依赖非规范化数据。一旦任务队列完成,它就可以从“正在更新”列表中删除该对象,并且一切都可以依赖于非规范化的数据。
复杂的版本甚至可以跟踪每个对象的编辑时间,因此给定的对象将知道它是否已被任务队列更新。