Apr 17

来源:http://www.oschina.net/question/12_32460

记得以前给大家介绍过视频网站龙头老大YouTube的技术架构, 相信大家看了都会有不少的感触,互联网就是这么一个神奇的东西。今天我突然想到,优酷网在国内也算是视频网站的老大了,不知道他的架构相对于 YouTube是怎么样的,于是带着这个好奇心去网上找了优酷网架构的各方面资料,虽然谈得没有YouTube那么详细,但多少还是挖掘了一点,现在总结 一下,希望对喜欢架构的朋友有所帮助。

一、网站基本数据概览

  • 据2010年统计,优酷网日均独立访问人数(uv)达到了8900万,日均访问量(pv)更是达到了17亿,优酷凭借这一数据成为google榜单中国内视频网站排名最高的厂商。
  • 硬件方面,优酷网引进的戴尔服务器主要以 PowerEdge 1950与PowerEdge 860为主,存储阵列以戴尔MD1000为主,2007的数据表明,优酷网已有1000多台服务器遍布在全国各大省市,现在应该更多了吧。

二、网站前端框架

从一开始,优酷网就自建了一套CMS来解决前端的页面显示,各个模块之间分离得比较恰当,前端可扩展性很好,UI的分离,让开发与维护变得十分简单和灵活,下图是优酷前端的模块调用关系:

这样,就根据module、method及params来确定调用相对独立的模块,显得非常简洁。下面附一张优酷的前端局部架构图:

三、数据库架构

应该说优酷的数据库架构也是经历了许多波折,从一开始的单台MySQL服务器(Just Running)到简单的MySQL主从复制、SSD优化、垂直分库、水平sharding分库,这一系列过程只有经历过才会有更深的体会吧,就像MySpace的架构经历一样,架构也是一步步慢慢成长和成熟的。

1、简单的MySQL主从复制:

MySQL的主从复制解决了数据库的读写分离,并很好的提升了读的性能,其原来图如下:

其主从复制的过程如下图所示:

但是,主从复制也带来其他一系列性能瓶颈问题:

  1. 写入无法扩展
  2. 写入无法缓存
  3. 复制延时
  4. 锁表率上升
  5. 表变大,缓存率下降

那问题产生总得解决的,这就产生下面的优化方案,一起来看看。

2、MySQL垂直分区

如果把业务切割得足够独立,那把不同业务的数据放到不同的数据库服务器将是一个不错的方案,而且万一其中一个业务崩溃了也不会影响其他业务的正常进行,并且也起到了负载分流的作用,大大提升了数据库的吞吐能力。经过垂直分区后的数据库架构图如下:

然而,尽管业务之间已经足够独立了,但是有些业务之间或多或少总会有点联系,如用户,基本上都会和每个业务相关联,况且这种分区方式,也不能解决单张表数据量暴涨的问题,因此为何不试试水平sharding呢?

3、MySQL水平分片(Sharding)

这是一个非常好的思路,将用户按一定规则(按id哈希)分组,并把该组用户的数据存储到一个数据库分片中,即一个sharding,这样随着用户数量的增加,只要简单地配置一台服务器即可,原理图如下:

如何来确定某个用户所在的shard呢,可以建一张用户和shard对应的数据表,每次请求先从这张表找用户的shard id,再从对应shard中查询相关数据,如下图所示:

但是,优酷是如何解决跨shard的查询呢,这个是个难点,据介绍优酷是尽量不跨shard查询,实在不行通过多维分片索引、分布式搜索引擎,下策是分布式数据库查询(这个非常麻烦而且耗性能)

四、缓存策略

貌似大的系统都对“缓存”情有独钟,从http缓存到memcached内存数据缓存,但优酷表示没有用内存缓存,理由如下:

  1. 避免内存拷贝,避免内存锁
  2. 如接到老大哥通知要把某个视频撤下来,如果在缓存里是比较麻烦的

而且Squid 的 write() 用户进程空间有消耗,Lighttpd 1.5 的 AIO(异步I/O) 读取文件到用户内存导致效率也比较低下。

但为何我们访问优酷会如此流畅,与土豆相比优酷的视频加载速度略胜一筹?这个要归功于优酷建立的比较完善的内容分发网络(CDN),它 通过多种方式保证分布在全国各地的用户进行就近访问——用户点击视频请求后,优酷网将根据用户所处地区位置,将离用户最近、服务状况最好的视频服务器地址 传送给用户,从而保证用户可以得到快速的视频体验。这就是CDN带来的优势,就近访问,有关CDN的更多内容,请大家Google一下。

Mar 29
首先,我们需要使用linux下另外一个ps命令查找与进程相关的PID号:ps aux | grep program_filter_word

ps a 显示现行终端机下的所有程序,包括其他用户的程序。
ps -A 显示所有程序。
ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。
ps -e 此参数的效果和指定"A"参数相同。
ps e 列出程序时,显示每个程序所使用的环境变量。
ps f 用ASCII字符显示树状结构,表达程序间的相互关系。
ps -H 显示树状结构,表示程序间的相互关系。
ps -N 显示所有的程序,除了执行ps指令终端机下的程序之外。
ps s 采用程序信号的格式显示程序状况。
ps S 列出程序时,包括已中断的子程序资料。
ps -t<终端机编号> 指定终端机编号,并列出属于该终端机的程序的状况。
ps u 以用户为主的格式来显示程序状况。
ps x 显示所有程序,不以终端机来区分。
最常用的方法是ps aux,然后再通过管道使用grep命令过滤查找特定的进程,然后再对特定的进程进行操作。

其次,使用kill命令结束进程:kill xxx

1)作用

kill命令用来中止一个进程。

2)格式

kill [ -s signal | -p ] [ -a ] pid ...
kill -l [ signal ]

3)参数

-s:指定发送的信号。
-p:模拟发送信号。
-l:指定信号的名称列表。
pid:要中止进程的ID号。
Signal:表示信号。

4)说明

进程是Linux系统中一个非常重要的概念。Linux是一个多任务的操作系统,系统上经常同时运行着多个进程。我们不关心这些进程究竟是如何分配的,或者是内核如何管理分配时间片的,所关心的是如何去控制这些进程,让它们能够很好地为用户服务。

Linux操作系统包括三种不同类型的进程,每种进程都有自己的特点和属性。交互进程是由一个Shell启动的进程。交互进程既可以在前台运行,也可以在后台运行。批处理进程和终端没有联系,是一个进程序列。监控进程(也称系统守护进程)是Linux系统启动时启动的进程,并在后台运行。例如,httpd 是著名的Apache服务器的监控进程。

kill命令的工作原理是,向Linux系统的内核发送一个系统操作信号和某个程序的进程标识号,然后系统内核就可以对进程标识号指定的进程进行操作。比如在top命令中,我们看到系统运行许多进程,有时就需要使用kill中止某些进程来提高系统资源。在讲解安装和登陆命令时,曾提到系统多个虚拟控制台的作用是当一个程序出错造成系统死锁时,可以切换到其它虚拟控制台工作关闭这个程序。此时使用的命令就是kill,因为kill是大多数Shell内部命令可以直接调用的。

5)应用实例

(1)强行中止(经常使用杀掉)一个进程标识号为324的进程:

#kill -9 324

(2)解除Linux系统的死锁

在 Linux中有时会发生这样一种情况:一个程序崩溃,并且处于死锁的状态。此时一般不用重新启动计算机,只需要中止(或者说是关闭)这个有问题的程序即可。当kill处于X-Window界面时,主要的程序(除了崩溃的程序之外)一般都已经正常启动了。此时打开一个终端,在那里中止有问题的程序。比如,如果Mozilla浏览器程序出现了锁死的情况,可以使用kill命令来中止所有包含有Mozolla浏览器的程序。首先用ps命令查找该程序的 PID,然后使用kill命令停止这个程序:

#kill -SIGKILL XXX

其中,XXX是包含有Mozolla浏览器的程序的进程标识号。

(3)使用命令回收内存

我们知道内存对于系统是非常重要的,回收内存可以提高系统资源。kill命令可以及时地中止一些"越轨"的程序或很长时间没有相应的程序。例如,使用top命令发现一个无用 (Zombie) 的进程,此时可以使用下面命令:

#kill -9 XXX

其中,XXX是无用的进程标识号。

然后使用下面命令:

#free

此时会发现可用内存容量增加了。

(4)killall命令

Linux下还提供了一个killall命令,可以直接使用进程的名字而不是进程标识号,例如:

# killall -HUP inetd

Dec 15
1.删除已有0.0.0.0路由
route delete 0.0.0.0 mask 0.0.0.0
2.添加外网路由
目标为 0.0.0.0,子网掩码为 0.0.0.0,下一个跃点地址为10.119.110.189
route add 0.0.0.0 mask 0.0.0.0 192.168.1.1
3.添加内网路由
目标为 10.0.0.0,子网掩码为 255.0.0.0,下一个跃点地址为10.119.110.189
route add 10.0.0.0 mask 255.0.0.0 10.119.110.189
子网掩码为0的位置,目标位置也必需为0,下一个跃点地址可以是网关/也可以是手动分配的IP地址。
Dec 12
查看:

[root@localhost ~]# date
六 11月 29 21:34:40 CST 2008

设定:

[root@localhost ~]# date 112921242008.29
六 11月 29 21:24:29 CST 2008

格式:date 月日时分年.秒


date -s 11/29/08

date -s 11:29:29


Linux硬件时钟查看与设定

把系统时间强制写入CMOS

[root@localhost ~]# hwclock -w

查看:
[root@localhost ~]# hwclock --show
2008年11月29日 星期六 01时34分43秒 -0.406003 seconds

设定:

[root@localhost ~]# hwclock --set --date="11/29/2008 22:29:00"

[root@localhost ~]# hwclock
2008年11月29日 星期六 22时29分11秒 -0.321602 seconds


系统时间和硬件时间的同步:

[root@localhost ~]# hwclock --hctosys

[root@localhost ~]# hwclock --systohc


--hctosys     set the system time from the hardware clock
--systohc     set the hardware clock to the current system time
Sep 2
想一次修改某个目录下所有文件的权限,包括子目录中的文件权限也要修改,要使用参数-R表示启动递归处理。
例如:

    [root@localhost ~]# chmod 777 /home/user

注:仅把/home/user目录的权限设置为rwxrwxrwx

    [root@localhost ~]# chmod -R 777 /home/user

注:表示将整个/home/user目录与其中的文件和子目录的权限都设置为rwxrwxrwx
Pages: 4/8 First page Previous page 1 2 3 4 5 6 7 8 Next page Final page [ View by Articles | List ]