网站扩展实例:1亿用户、50亿pv的Tagged架构进化史

2023-11-05 12:48

本文主要是介绍网站扩展实例:1亿用户、50亿pv的Tagged架构进化史,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一家2004年创建的试水社交网站,经过7年的成长和扩展,现在已经拥有了1亿用户。平均50亿次的pv,承担在1000多台服务器的网站架构上。Tagged网站,现在承载了1亿个用户、1千台服务器和50亿次页面浏览量。这个过程是如何实现的?本文中,Tagged的CTO兼联合创始人 Johann Schleier-Smith 将为我们介绍。

AD:

【51CTO 8月16日外电头条】一家2004年创建的试水社交网站,经过7年的成长和扩展,现在已经拥有了1亿用户。平均50亿次的pv,承担在1000多台服务器的网站架构上。本文将要介绍的就是这个叫Tagged的网站——Tagged架构实例:1亿个用户、1千台服务器和50亿次页面浏览量。下面,Tagged的CTO兼联合创始人 Johann Schleier-Smith 将为我们介绍Tagged网站架构的成长历程。

自2004年以来,Tagged从一家试水社交领域的小不点网站,逐渐变成全球最大的社交网络之一,数百万的成员访问该网站以结交新成员,每个月的页面浏览量达到50亿次。这个逐步发展的历程迫使我们Tagged不断完善网站架构,最终获得了功能异常强大的平台。

第一个阶段:2004年,PHP Web应用程序、10万个用户和15台服务器

2004年,PHP Web应用程序、10万个用户和15台服务器

孵化器有着一种快速成型文化:每年通常推出两个新概念,寻觅其中的大赢家。正是在这样的文化中,Tagged 应运而生。LAMP是适合这种类型的工作的自然选择;这种工作注重灵活性和快速开发周期。当时,Java开发主要面向大企业的开发工作,Python吸引的编程员寥寥无几,Perl方面的编程员又不是我们所要的那一种。我们还知道,雅虎是PHP的大力支持者;所以一旦有需要,完全有可能扩展业务规模。

我在以前的项目上运行MySQL方面有着丰富的经历,这让我对这项技术爱恨交加。本着尝试的精神,我们为Tagged购买了几份入门级Oracle许可证,看看甲骨文的技术是不是用起来更好。

值得注意的是,许多构建的小型网站仍然就像早期的Tagged。具有一种简单的美;无状态的PHP与有状态的Oracle之间的双向分离正是一台服务器中最棘手的部分,而额外的Web显示计算能力很容易添加。

第二个阶段:2005年,缓存PHP Web应用程序、100万个用户和20台服务器

2005年,缓存PHP Web应用程序、100万个用户和20台服务器

即使只有在8台服务器的时候,Tagged的网站流量也要比大多数人所知道的来得多。幸运的是,分布式内存缓存系统memcached带来了两个优势:既消除了90%以上的数据库读操作,又确保含有大量不同信息的社交网络面面可以迅速显示。

自一开始,我们的对象缓存注重显式缓存更新,支持更简单的技术,比如删除无效的键;或者根据计时器,使失效数据无效。这种方法的缺点是代码比较复杂,但大幅减轻了数据库负载,而且使网站保持快速运行,涉及经常更新的对象时更是如此。

我们的网站继续越来越复杂,在标准的社交网络功能(交友、个人档案和讯息)的基础上,添加了搜索和社交发现等功能。我的团队说服我使用Java来建立搜索功能,那样我们就能得益于Lucene库。当我们学会了让Java顺畅运行后,我有一种如释重负的感觉;我早期用过JDK 1.0,感觉不爽,所以不大情愿使用Java,但是后来却对这个平台满怀热情。

第三个阶段:2006年,数据库扩展、1000万个用户和100台服务器

2006年,数据库扩展、1000万个用户和100台服务器

此时Tagged已拥有1000万个注册用户,随时都有成千上万个用户在线,我们开始着手解决我一直忧心忡忡的挑战。那时我们刚筹集到了一笔资金,竭力寻求发展,但是数据库亟需添加容量。我们进行了一次又一次的缓存或SQL调整和优化,但服务器的处理器其占用率还是会一再逼近100%大关。

向上扩展系统的想法是个权宜之计,但是多插座服务器硬件动辄数百万美元,于是我们选择了Oracle真正应用集群RAC,该系统让我们可以使用标准网络系统来连接数量众多的大众化Linux主机,以构建一个庞大的数据库。再结合最新处理器具有的优势,Oracle RAC的容量比我们的第一台数据库服务器足足增加了20倍,这一点很重要,而且允许应用程序开发人员可以继续致力于开发新的功能特性。

Tagged通过结合来自一个庞大内存中数据集的统计数字,开始提供个性化的人员匹配(people-matching)推荐服务。用PHP实现这一点完全不现实,于是Java进一步渗透到了我们的环境中。

第四个阶段:2007年,数据库拆分、5000万个用户和500台服务器

2007年,数据库拆分、5000万个用户和500台服务器

毫无疑问,拆分数据库是最具有难度的任务,也是在扩展Tagged方面最具有成效的技术。由于在多个数据库之间分割用户,我们最终拥有了这种设计:在所有地方都允许我们只要添加硬件,就可以进行扩展。

我们Tagged的一条规定是,将每个表分成64个分区;我们牢牢遵守这个不成文的规定,除非有着非常诱人的理由才允许有例外。只有得益于游戏玩家之间高性能受保护事务的某些游戏才在单独的数据库中垂直分区。

拆分现有的数据意味着针对数TB的数据进行复杂的转换工作。一开始,我们每次逐个着手解决功能特性,依赖应用程序代码来代替连接(join),但最后我们还是在应用程序的核心部分遇到了一大批表,这些表的结合得太紧密了,这个方法行不通。于是我们编写了生成SQL的迁移代码,导出、转换和重新装入了数亿行的数据,并使用触发器来跟踪源系统上面出现的变化,逐渐更新目标,那样最后的同步所带来的停运时间不到30分钟。

拥有许多数据库意味着拥有许多的数据库连接。尤其是由于我们添加了更多的“社交发现”功能(比如我们的第一项约会功能Meet Me),拆分工作可能会让PHP不堪重负,毕竟PHP缺少甲骨文的连接池技术。为了解决这个问题,我们开发了一款Java应用程序,负责提供运行查询的Web服务;该应用程序还继续提供一个非常方便的监控点,便于轻松自如地处理数据库故障。

第五个阶段:2010年,架构完善和扩展、8000万个用户和1000台服务器

2010年,架构完善和扩展、8000万个用户和1000台服务器

这次我们把时间提前几年。解决了关键的数据库扩展性问题后,我们发现通过添加硬件来支持扩展相当容易。PHP和memcached继续很好地服务于我们,支持功能特性的快速开发。

在这一段期间,扩展性方面的考量因素转向了减少故障和应对越来越多的易损坏部件所带来的威胁。通过负载均衡器的运行状况检查和自动关闭毫无反应的服务,实现了针对Web层的全方位保护,避免了各种相关问题。我们在设计核心组件的架构时还考虑到了弹性;比如说,如果memcached系统因连接过多而出现过载,那么一旦这个负担卸下,它必须立即复原。

Java扮演了极其重要的角色,一方面归因于Java越来越得到接受,拥有相应专长的人也越来越多;另一方面是由于面临的挑战越来越多。为了对付垃圾邮件及其他滥用现象,我们的算法充分利用了庞大的共享内存空间,还充分利用了计算密集型方法。社交游戏也得益于Java的高性能和并发控制,但面临的代价是系统很复杂;现在不同的应用程序池比以前多得多,有待我们加以管理。

展望未来

如今,Tagged每个月给数百万成员带来50亿次的页面浏览量。由于我们获得了可扩展的设计,因而可以将大部分精力花在构建能够更好地服务于用户的功能特性上。我们拥有开发可扩展软件的高效工具,但我们可以设想工具会出色得多,于是目前的精力和资源主要集中于软件库,提高编程人员的效率和生产力,并且改进Stig——Stig是我们即将推出的采用开源技术的基于图形的数据库项目,该项目为大规模的社交网络、实时服务和云应用系统而设计。

原文:Tagged Architecture - Scaling To 100 Million Users, 1000 Servers, And 5 Billion Page Views

这篇关于网站扩展实例:1亿用户、50亿pv的Tagged架构进化史的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/349973

相关文章

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Spring Boot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)

《SpringBoot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)》本文将以一个实际案例(用户管理系统)为例,详细解析SpringBoot中Co... 目录引言:为什么学习Spring Boot分层架构?第一部分:Spring Boot的整体架构1.1

k8s admin用户生成token方式

《k8sadmin用户生成token方式》用户使用Kubernetes1.28创建admin命名空间并部署,通过ClusterRoleBinding为jenkins用户授权集群级权限,生成并获取其t... 目录k8s admin用户生成token创建一个admin的命名空间查看k8s namespace 的

PyQt6 键盘事件处理的实现及实例代码

《PyQt6键盘事件处理的实现及实例代码》本文主要介绍了PyQt6键盘事件处理的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起... 目录一、键盘事件处理详解1、核心事件处理器2、事件对象 QKeyEvent3、修饰键处理(1)、修饰键类

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

MySQL的配置文件详解及实例代码

《MySQL的配置文件详解及实例代码》MySQL的配置文件是服务器运行的重要组成部分,用于设置服务器操作的各种参数,下面:本文主要介绍MySQL配置文件的相关资料,文中通过代码介绍的非常详细,需要... 目录前言一、配置文件结构1.[mysqld]2.[client]3.[mysql]4.[mysqldum

Java Stream流以及常用方法操作实例

《JavaStream流以及常用方法操作实例》Stream是对Java中集合的一种增强方式,使用它可以将集合的处理过程变得更加简洁、高效和易读,:本文主要介绍JavaStream流以及常用方法... 目录一、Stream流是什么?二、stream的操作2.1、stream流创建2.2、stream的使用2.

springboot项目中集成shiro+jwt完整实例代码

《springboot项目中集成shiro+jwt完整实例代码》本文详细介绍如何在项目中集成Shiro和JWT,实现用户登录校验、token携带及接口权限管理,涉及自定义Realm、ModularRe... 目录简介目的需要的jar集成过程1.配置shiro2.创建自定义Realm2.1 LoginReal

Python跨文件实例化、跨文件调用及导入库示例代码

《Python跨文件实例化、跨文件调用及导入库示例代码》在Python开发过程中,经常会遇到需要在一个工程中调用另一个工程的Python文件的情况,:本文主要介绍Python跨文件实例化、跨文件调... 目录1. 核心对比表格(完整汇总)1.1 自定义模块跨文件调用汇总表1.2 第三方库使用汇总表1.3 导

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件