繁体   English   中英

Google数据存储区

[英]Google Datastore

我计划使用MySQL,但Google Datastore看起来可能是一个可能的解决方案,我不必担心管理服务器这是一个很大的优势。 我需要存储一件事,消息。 我计划有一个MySQL消息传递表,其中包含用户向其他用户发送的消息。

我希望我能以某种方式将我的MySQL消息表有效地翻译成Google Datastore。 我的要求是使用MySQL的解决方案是:

消息只能由一个用户发送给另一个用户。 首次读取时,此消息需要更新,说明它已被读取,因此如果已读取,则需要更新一次。 用户必须能够查看按最新订购的所有已发送消息以及最新订购的所有消息。

我的初始设计看起来像这样:

消息表:

Message_ID (BIGINT) PK auto_increment
FromUser (INT 16)
ToUser (INT 16)
DateCreated (Timestamp)
MessageText (Varchar (500) )
HasRead (TINYINT (0=false, 1=true) )

将运行的查询将包括:

SELECT * FROM messages WHERE FromUser = '10000000' ORDER BY DateCreared DESC LIMIT [starting pagination value], 10 ; //get all users sent messages - newest first, get 10 at a time

SELECT * FROM messages WHERE ToUser= '10000000' ORDER BY DateCreared DESC LIMIT [starting pagination value], 10 ; //get all user's received messages - newest first, get 10 at a time

UPDATE messages SET HasRead = 1 WHERE Message_ID = '123456789'; // When a message has been read update it to show it has been read.

因此,我将拥有以下索引:

-Message_ID(主索引) - (FromUser,DateCreated)BTREE DESC - (ToUser,DateCreated)BTREE DESC附加“希望有功能,但如果它影响性能或者实现太复杂”,它可以没有它的要求“让用户与其他用户一起查看他们的消息:

SELECT * FROM messages WHERE (FromUser = '1000000 and ToUser = '2000000') OR (FromUser = '2000000' and ToUser = '1000000') ORDER BY DateCreated DESC [starting pagination value], 10 ; // Get all the messages sent between user 1000000 and user 2000000 - newest first, fetch 10 at a time. I was thinking of creating a new column which would be be a concatenation of [smaller_userid]-[larger_userid] and search on this field instead. If this was the case I would have an additional composite index on this new column + DateCreated. SELECT * FROM messages WHERE concateduser = '1000000-2000000' ORDER BY DateCreated DESC [starting pagination value], 10 ;

我们相信这会起作用,但我们目前有一个活跃的用户社区,并且估计我们推出该功能时会大量使用它。 因此,我们还希望计划未来能够扩展(现在过早,但我们认为这是一个非常简单的特性,并且希望现在能很好地设计它以节省我们未来的时间)。

所以这就是我计划用MySQL做的事情。 这可以转换为有效的Google数据存储区吗?

我研究了一些解决方案,但它们会非常昂贵。 我的第一个想法是让每条消息成为一个实体。 然后,该实体将具有To,From,hash(user1 + user2)属性的索引。 这将允许我访问,来自和组合用户消息。 问题是写入会很昂贵,如果读取的消息很昂贵则更新。 查询也很昂贵,如果我最初加载10条消息,则需要1 + 10个读取单元。 我尝试了另一种在一个实体内存储N条消息的解决方案。 对于每个用户,我需要存储他们当前所在的实体,这也变得很昂贵,因为对于每个消息,我需要两次写入相同的数据(每个用户一次),更新必须发生在两个集合中,另外还有附加读取以在插入或读取消息时获取用户所在的当前实体。 我正在寻找更好的解决方案来满足这个简单的要求。

这一切都取决于你对昂贵的定义。

你的一条消息,一个实体设计当然似乎是最明智的。

使用4次写入(实体+索引)发送一百万条消息将花费:

(0.6 / 100000) * 4 * 1000000 = 24美分

另外24美分用于标记为已读

如果我们假设每条消息将导致至少一个读取查询(对于一组10) (0.6 / 100000) * 11 * 1000000 = 66美分

如果我们假设每条消息大约需要150个字符,那么每月存储它们将花费(1000000 * 150 / 1024000000) * 0.18 =一个月大约2.6美分,但这是附加的,所以一年后你将支付31.2美分,等等

那么我们发现了什么? 阅读相对昂贵,或者说查询是昂贵的。 你会做很多事情。 您可能还没有考虑过不同的场景(例如,如果您想向用户显示他们有多少未读消息?)。

因此,您需要积极地记忆这些查询,但随后您将了解最终的一致性 简而言之,对于数据存储区,查询不会(始终)包含您事先执行的所有写入结果(仅最终)。 这使得缓存很难,因为很难知道您的查询何时是最新的。

您可能最终会使用祖先和实体组来解决此问题,实质上您的消息将围绕根实体(代表用户)进行分组。 由于这提供了强大的一致性和原子性,您会发现这提供了保留某些信息的自然点。 该用户相关实体可以存储诸如未读消息计数之类的内容,或者甚至是单个实体中的所有未读消息的id的列表,最后10个消息等。

然后可以积极地memcached( 写入时 ),消息本身也可以。 这意味着在理想情况下,您只需编写消息和用户实体,并且当用户单击它而不进行单个查询甚至读取时,您可以显示未读消息计数,前10条消息和消息本身。

祖先查询带有成本,而不是美分,但能够进行写入。 对于一个组中的所有实体(因此一个用户),这将限于(最差)一个每秒写入总数。 这不应该是一个问题(除非你希望用户每隔几秒钟收到一次消息),但你仍然需要考虑写入有时会失败并且必须重试。

选择是否使用祖先是一个重要的决定,这不是不可能,但后来很难迁移到这个模型。 但是,在你看到实际成本之前,我会亲自推迟其他积极的性能优化。 无论你是每月还是每秒发送一百万条消息,基本上性能在这个模型中都会保持不变,并且你可以更好地花钱购买其他东西以增加用户的收入,而不是试图从Datastore中挤出最后几分钱。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM