社交产品后端架构设计 (2)

正确的认识和理解session数据是非常重要的。Session数据将帮助我们保持用户的状态。Session数据必须使用与服务器无关的方式,方便我们服务端可伸缩部署。这将有助于保持我们的设计灵活,确保session不会绑定到特定的节点或服务器。

我们得用一种新的方式来更新用户的实际session,如果用户的session终止,我们仍然可以帮助用户从一个地方,他离开的地方重新恢复信息。

这是特别重要的,在我们的场景中,连接是不可靠的,数据丢包是很正常的。数据必须能够被跨节点访问,因此需要可用性和可扩展性。我们可以很好的使用MongoDB本身来保存数据。后来,我们想转移到纯粹的键值存储,如Redis。

注:所有推荐和离线作业都应该只运行在非服务节点上。

索引

索引是我们系统的关键。用户可以搜索任何内容,这是我们的主要用例之一。为了提升搜索性能,我们必须非常认真地对待索引。这里有两点需要考虑:首先是,创建索引本身,然后就是索引系统本身。

为了做一个有意义的搜索系统,我们必须设计一个实时索引,针对一段时间窗口的实时数据进行处理。首先,我们可以写一个非常简单的系统,对产生的内容数据做倒排索引。后来,随着输入数据的增加,我们可以方便地用实时数据处理引擎取代它,如Apache的Storm,这是一个分布式的,容错和高度可扩展的系统。它可以负责生成索引的逻辑。

索引系统:由于Lucene受欢迎程度和其性能,因此,Lucene是一个显而易见的好选择;它的性能是无与伦比的。我们可以使用SolrCloud。它已经透明的支持分片,复制和读写方面的容错。

队列&消息推送

每次我们的应用程序被触发一个事件,我们将需要向他/她的追随者/朋友推送消息。重要的是,我们的系统不能错过任何这些信息,更重要的是,能够在发生故障时恢复这些事件。为了达到这些要求,我们必须寻找一个队列解决方案。我们可以使用ActiveMQ,这是最可靠的队列软件。它支持集群的高可用性,支持分布式队列。

消息推送是另一个领域,要把通知发送给我们的用户。在这里我们需要估计一下规模。我们应该准备好支持像nps这样上亿的规模。这里有许多选择,但也许pyapns、CommandIQ和APP Booster才是最流行的。

我们需要自己管理一些事情,特别是要保证消息传递可靠性,即使用户的设备处于离线状态。我建议我们实现一个双向的系统,保持状态的通知,并在后台持久化到磁盘。所以每次一个通知失败时,它的状态都被处理并标上状态码,添加到重试队列中。最后,当通知被送达,移出重试出列。

缓存策略

像我们这样的系统,我们的目标是使其支撑十亿RPS,因此,好的缓存策略是极重要的。我们的业务逻辑会在多层缓存中,并且能够智能的清除失效缓存。让我们看看最顶层缓存。

应用层缓存(内容缓存):为了最大限度地减少缓存未命中,并确保缓存始终是最新的数据,我们必须寻找一个从未过期的缓存,并始终保持数据。这基本上意味着在一般使用情况下,我们将永远不用查询我们的数据库,因此节省了大量的资源。我们还应该确保我们缓存的数据总是以一种不需要额外处理的格式,随时准备好呈现。这基本上意味着将我们的在线负载转换为离线负载,从而节省了延迟。要做到这一点,我们必须确保每一次的内容被输入到系统中,我们要做两件事情:

a)原内容是非规格化形式保存在缓存。为了安全起见,我们将永远设置一个有效的期限。

b)原内容也写在我们的数据存储区中。

我们使用Redis来做这个缓存,Redis是一种具有良好故障恢复的内存缓存。它具有高度的可扩展性,较新的版本透明的支持了数据分片。支持主从节点配置。最好的部分是,我们能够保存任何格式的数据,这使得它很容易做增量写,这是至关重要的,我们支持内容feeds

还值得指出的是,我们需要支持对大内容对象进行大量的读 - 修改 - 写操作和少量读,Redis是已知的,对这些操作在性能方面是最好的。

缓存代理:反向代理层的缓存也是至关重要的。它有助于减少直接请求我们服务器的负载,从而减少延迟。为了使代理服务器缓存更有效,需要正确设置HTTP响应头。代理服务器有很多种,但最受欢迎的是nginx和ATS。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzszfj.html