Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
生活在大规模互连的社会中,这意味着有时候你也成了社交网络中的一部分 。 使用社交网络与朋友、同事和家人保持联系,有时还会与有共同兴趣的人分享我们的激情。
作为工程师或开发人员,你可能想知道这些网络如何存储和互连数据。 或者,你甚至可能承担着为特定利基市场创建或构建新社交网络的任务。 这时就会产生一个大问题:所有这些数据是如何存储的?
假设你正在创建一个新型时尚的社交网络,用户可以在此网络中发布带有相关媒体(如图片、视频,甚至音乐)的文章。 用户可以对帖子发表评论并打分以进行评级。 主网站登录页上将提供用户可见并可与之交互的帖子源。 这种方法听起来并不复杂,但为了简单起见,我们就此止步。 可以深入到受关系影响的自定义用户源中,但这超出了本文的目标。
那么,如何确定存储这些数据的方式以及位置?
你可能有使用 SQL 数据库的经验,或者了解数据的关系模型。 可开始绘制如下内容:
非常标准且美观的数据结构,但却不可扩展。
不要误会,我一直致力于开发 SQL 数据库。 它们很棒,但就像每种模式、实践方法和软件平台一样,它并不适用于所有场景。
为什么在此方案中 SQL 不是最佳选择? 我们来看一下单个帖子的结构。 如果想在网站或应用程序中显示帖子,我需要进行查询,并且需要联接八个表(!)才能显示一个帖子。 现在请想象一下:一系列帖子动态地加载并显示在屏幕上。你可能就明白我的意思了。
可以使用一个具备足够计算能力的庞大SQL实例来解决数以千计的查询,其中通过许多联接来提供内容。 但当已经有一个更简单的解决方案存在时,为什么还要选择这种呢?
NoSQL 之路
本文将引导您使用 Azure 的 NoSQL 数据库 Azure Cosmos DB 以成本效益高的方式对社交平台的数据进行建模。 它还介绍如何使用其他 Azure Cosmos DB 功能,例如 gremlin 的 API。 使用 NoSQL 方法以 JSON 格式存储数据并应用非规范化,就可以将以前的复杂帖子转换为单个文档:
{
"id":"ew12-res2-234e-544f",
"title":"post title",
"date":"2016-01-01",
"body":"this is an awesome post stored on NoSQL",
"createdBy":User,
"images":["https://myfirstimage.png","https://mysecondimage.png"],
"videos":[
{"url":"https://myfirstvideo.mp4", "title":"The first video"},
{"url":"https://mysecondvideo.mp4", "title":"The second video"}
],
"audios":[
{"url":"https://myfirstaudio.mp3", "title":"The first audio"},
{"url":"https://mysecondaudio.mp3", "title":"The second audio"}
]
}
可以使用单个查询获得,且无需联接。 此查询非常简单直观,且在预算方面,它所需要的资源更少,但得到的结果更好。
Azure Cosmos DB 确保所有属性都通过其自动索引进行索引。 自动索引甚至可以进行自定义。 通过此无架构方法,可存储具有不同动态结构的文档。 也许明天你会想让帖子有一个与之相关的类别或话题标签列表? Azure Cosmos DB 使用添加的属性处理新文档,而无需我们执行额外的工作。
可以将对帖子的评论视为具有父属性的其他帖子。 (这可以简化对象映射。)
{
"id":"1234-asd3-54ts-199a",
"title":"Awesome post!",
"date":"2016-01-02",
"createdBy":User2,
"parent":"ew12-res2-234e-544f"
}
{
"id":"asd2-fee4-23gc-jh67",
"title":"Ditto!",
"date":"2016-01-03",
"createdBy":User3,
"parent":"ew12-res2-234e-544f"
}
并且所有社交互动都可以作为计数器存储在单个对象上:
{
"id":"dfe3-thf5-232s-dse4",
"post":"ew12-res2-234e-544f",
"comments":2,
"likes":10,
"points":200
}
创建信息源只是创建可以按给定相关顺序保存帖子 ID 列表的文档而已。
[
{"relevance":9, "post":"ew12-res2-234e-544f"},
{"relevance":8, "post":"fer7-mnb6-fgh9-2344"},
{"relevance":7, "post":"w34r-qeg6-ref6-8565"}
]
你可以有一个“最新”流,其中的帖子按创建日期排序。 或者可以有一个“最热门”的流,其中包含过去 24 小时内点赞数最多的帖子。 甚至可以根据关注者和兴趣等逻辑为每个用户实现自定义流。 它仍然是一个文章列表。 虽然如何生成这些列表还是一个问题,但读取性能不会受到阻碍。 获取其中一个列表后,可以使用 IN 关键字向 Azure Cosmos DB 发送单一查询,逐页获取帖子。
可以使用 Azure App Services 的后台进程构建数据流。 创建帖子后,可以使用 Azure StorageQueues 触发后台处理,从而基于自己的自定义逻辑在流中实现后期传播。
通过使用同样的技术,帖子上的评分和点赞可以以延迟方式处理,从而创建一个实现最终一致性的环境。
关注者更棘手。 Azure Cosmos DB 具有文档大小限制,读取/写入大型文档可能会影响应用程序的可伸缩性。 因此,您可以考虑将关注者存储为具有以下结构的文档:
{
"id":"234d-sd23-rrf2-552d",
"followersOf": "dse4-qwe2-ert4-aad2",
"followers":[
"ewr5-232d-tyrg-iuo2",
"qejh-2345-sdf1-ytg5",
//...
"uie0-4tyg-3456-rwjh"
]
}
此结构可能适用于拥有数千位关注者的用户。 但是,如果某些名人加入排名,此方法会导致文档大小较大,最终可能会达到文档大小上限。
为了解决此问题,可以使用一种混合方法。 可以在用户统计信息文档中存储关注者人数:
{
"id":"234d-sd23-rrf2-552d",
"user": "dse4-qwe2-ert4-aad2",
"followers":55230,
"totalPosts":452,
"totalPoints":11342
}
可以使用 Azure Cosmos DB API for Gremlin 存储关注者的实际图,以便为每个用户创建 顶点,并通过边维护“A-follows-B”关系。 使用 API for Gremlin 不仅可以获取某位用户的关注者,而且还能创建更复杂的查询以推荐具有共同点的用户。 如果在图形中添加用户喜欢或感兴趣的内容类别,就可以开始布置智能内容发现、推荐关注用户感兴趣的内容和查找具有共同点的用户等体验。
仍然可以使用用户统计信息文档在 UI 或快速配置文件预览中创建卡片。
“阶梯”模式和数据重复
你可能已注意到,在引用帖子的 JSON 文档中,某个用户出现了多次。 你猜得没错,这些重复意味着,由于这种反规范化,描述用户的信息可能会出现在多个地方。
若要实现更快速的查询,您会接受数据重复。 此负面影响的问题在于,如果某些操作导致用户的数据发生更改,那么需要查找该用户曾经执行过的所有活动并对这些活动全部进行更新。 听上去不太实用,对不对?
通过识别用户的关键属性解决该问题。对于每个活动,都会在应用程序中显示此属性。 如果在应用程序中直观显示一个帖子并仅显示创建者的姓名和照片,那么为什么还要在“createdBy”属性中存储用户的所有数据呢? 如果对于每一条评论都只显示用户的照片,那么的确不需要该用户的其余信息。 这就会涉及到我所称的“阶梯模式”。
我们以用户信息为例:
{
"id":"dse4-qwe2-ert4-aad2",
"name":"John",
"surname":"Doe",
"address":"742 Evergreen Terrace",
"birthday":"1983-05-07",
"email":"john@doe.com",
"twitterHandle":"\@john",
"username":"johndoe",
"password":"some_encrypted_phrase",
"totalPoints":100,
"totalPosts":24
}
通过查看此信息,可以快速检测出哪些是重要的信息,哪些不是,从而就会创建一个“阶梯”:
最简单的一步称为 UserChunk,这是标识用户的最小信息块并可用于数据重复。 通过减少重复数据的大小直到只留下要“显示”的信息,可以降低大规模更新的可能性。
中间步骤称为用户。 它是Azure Cosmos DB 上大多数依赖于性能的查询(访问次数最多且最关键)上使用的完整数据。 它包括由 UserChunk 表示的信息。
最大的是扩展用户。 它包括重要用户信息和其他不需要快速读取或最终使用的数据,如登录过程。 此数据可以存储在 Azure Cosmos DB 外部、Azure SQL Database或Azure Storage表中。
为什么要拆分用户,甚至将此信息存储在不同的位置? 因为,从性能角度考虑,文档越大,查询成本将越高。 保持文档精简,包含正确的信息,以执行所有依赖性能的社交网络查询。 存储用于可能场景的其他额外信息,例如完整配置文件编辑、登录以及用于使用情况分析和大数据计划的数据挖掘。 你真的不在乎数据挖掘的数据收集速度是否较慢,因为它在Azure SQL Database上运行。 你确实担心你的用户能否获得快速而精简的体验。 存储在 Azure Cosmos DB 上的用户将呈现类似于以下代码:
{
"id":"dse4-qwe2-ert4-aad2",
"name":"John",
"surname":"Doe",
"username":"johndoe"
"email":"john@doe.com",
"twitterHandle":"\@john"
}
帖子将显示如下内容:
{
"id":"1234-asd3-54ts-199a",
"title":"Awesome post!",
"date":"2016-01-02",
"createdBy":{
"id":"dse4-qwe2-ert4-aad2",
"username":"johndoe"
}
}
当区块属性受影响需要进行编辑时,可轻松找到受影响的文档。 只需使用指向已编入索引属性的查询,例如SELECT * FROM posts p WHERE p.createdBy.id == "edited_user_id",然后更新数据块。
搜索框
幸运的是,用户会生成大量内容。 您应该能够提供搜索和查找这些内容的功能,这些内容可能没有直接出现在用户内容流中。可能是因为您没有关注特定的创作者,或者是因为您只是想找到六个月前发布的旧帖子。
由于使用的是 Azure Cosmos DB,因此可以在几分钟内使用 Azure AI Search 轻松实现搜索引擎,而无需键入搜索过程和 UI 以外的任何代码。
为什么此过程如此简单?
Azure AI Search 实现了一个称为 Indexers 的功能,这是一种与数据仓库进行集成的后台进程,能够神奇地自动添加、更新或删除索引中的对象。 它们支持 Azure SQL Database 索引器、Azure Blobs 索引器,值得庆幸的是,Azure Cosmos DB 索引器。 将信息从 Azure Cosmos DB 转换为Azure AI Search非常简单。 这两种技术都以 JSON 格式存储信息,因此只需创建索引并从要编制索引的文档中映射属性。 就这么简单! 根据数据的大小,云基础结构中最好的搜索即服务解决方案可在几分钟内搜索所有内容。
有关Azure AI Search的详细信息,请访问 Hitchhiker 的搜索指南。
基础知识
存储所有日益增长的此内容后,你可能会考虑:我如何处理来自我的用户的所有此信息流?
答案非常简单:投入使用并从中进行学习。
但是,可以学到什么? 几个简单的例子包括情感分析、基于用户偏好的内容推荐,或者甚至一个自动化的内容审查器,它确保你的社交网络上发布的内容对家庭安全。
现在我已经吸引住了你,你可能会认为需要一些数学科学的博士学位才能从简单的数据库和文件中提取这些模式和信息,其实不然。
另一个可用选项是使用
多个区域的规模化社交体验
我必须讨论最后但同样重要的一个重要话题:可伸缩性。 设计架构时,每个组件都应该能够独立扩展。 你最终需要处理更多数据,或者希望具有更大的地理覆盖范围。 值得庆幸的是,使用 Azure Cosmos DB 实现这两个任务是一种开箱即用的体验。
Azure Cosmos DB 支持现成动态分区。 它会根据给定的分区键自动创建分区,分区键在文档中定义为属性 。 定义正确的分区键操作必须在设计时完成。 有关详细信息,请参阅 Azure Cosmos DB 中的分区。
对于社交体验,必须将分区策略与查询和写入方式保持一致。 (例如,推荐在同一分区内进行读取,并通过在多个分区上分散写入来避免“热点”。)某些选项为:基于临时键的分区(日/月/周)、按内容类别、按地理区域,或按用户。 这完全取决于查询数据的方式,并在社交体验中显示数据。
Azure Cosmos DB 以透明方式在所有分区上运行查询(包括 aggregates),因此无需在数据增长时添加任何逻辑。
一段时间后,最终流量会增加,资源消耗(通过 RU 即“请求单位”进行度量)也会增加。 随着用户群的增长,你将更频繁地读取和写入。 用户群开始创建和阅读更多内容。 因此,扩展吞吐量的能力至关重要。 增加 RU 非常容易。 您可以在 Azure portal 上进行一些选择,或者通过 API 发出命令 来完成此操作。
如果情况不断好转会怎样? 假设来自其他国家/地区或大洲的用户注意到你的平台并开始使用。 真是太棒了!
可是等等! 你很快就会发现他们使用平台的体验并不是最佳体验。 他们距离你的运营区域太远,会出现非常严重的延迟情况。 你显然不希望他们放弃。 如果有一种简单的方法可以扩展多区域覆盖范围就好了。 确实有!
通过 Azure Cosmos DB,您可以将数据复制到多个区域,并且可以在 client 代码中透明地选择并自动选择可用区域。 此进程还意味着可以拥有多个故障转移区域。
将数据复制到多个区域时,需确保客户端可以利用该数据。 如果使用 Web 前端或从移动客户端访问 API,则可以部署 Azure Traffic Manager 并在所有所需区域克隆Azure App Service,使用性能配置来支持扩展的多区域覆盖范围。 当客户访问您的前端或 API 时,他们将被路由到最近的 App Service,从而连接到本地 Azure Cosmos DB 副本。
结论
本文阐明了一些替代方法,即使用低成本服务完全在Azure上创建社交网络。 它通过鼓励使用一种称为“Ladder”的多层存储解决方案和数据分布,来实现成果。
事实上,对于此类方案并没有万能方法。 这是通过卓越服务的组合所创造的协同效应,使我们能够构建出色的体验:Azure Cosmos DB 的速度和自由为出色的社交应用程序提供支持,如 Azure AI Search 这样的一流搜索解决方案背后的智能,Azure App Services 的灵活性不仅用于托管与语言无关的应用程序,还支持强大的后台进程,以及可扩展的 Azure Storage 和 Azure SQL Database 用于存储海量数据,还有 Azure Machine Learning 的分析能力来创建能向流程提供反馈的知识和智能,帮助我们将合适的内容传递给合适的用户。
后续步骤
若要详细了解 Azure Cosmos DB 的用例,请参阅 Common Azure Cosmos DB 用例。