Database Sharding@Netlog 详细的描述了 Netlog 数据库架构的演变过程,文章浅显易懂,非常值得学习。本文数据、图片均来自:Database Sharding at Netlog, with MySQL and PHP

数据

约4000万活跃用户
每月约5000万独立访问
每月约50亿 PV 和 每月 60亿 online minutes
在数据库 sharding 以前,高峰时期每秒3000次以上数据库查询
26种语言,30多个国家,5个最活跃的国家主要集中在欧洲

技术平台

Squid
Lighttpd, Apache
PHP
MySQL
Debian
Memcached
Sphinx
and many more.

Netlog 数据库架构的历史

netlog 从7年前的一个 hobby project 发展而来,数据库从单台服务器扩展到树型多台服务器。

DB Setup 1: Master (W)

读写都在一台服务器上。

DB Setup 2: Master (W) + Slaves (R)

读写分离,写操作(INSERT/UPDATE/DELETE)在 Master 上执行,读操作(SELECT)在1个或者多个 Slaves 上执行。这种方案适合读比写多的情况,比如读写比例4:1的情况,不适合写比读多的情况,比如读写比例1:4。Slaves 通过同步 Master 的 binlog 文件,并且执行其中所有的写操作来同步数据库。这样会带来数据同步的问题,可能会造成数据滞后,比如一个数据刚写在 Master 上,Slaves 还来不及同步就被读取,读取的数据实际上是以前的数据,造成数据滞后。如果数据恰好很重要,比如用户刚换密码(密码写入 Master),然后用新密码登录(从 Slaves 读取密码),会造成密码不一致,导致用户短时间内登录出错。所以在这种需要读取实时数据的时候最好从 Master 直接读取,避免 Slaves 数据滞后现象发生。还好,需要读取实时数据的时候不多,比如用户更改了邮件地址,就没必要马上读取,所以这种 Master-Slaves 架构在多数情况下还是有效的。

DB Setup 3: Vertical Partitioning

DB Setup 2 的架构有个问题,就是能有效应付读多写少的情况,如果读少写多比如读写1:4就不是那么有效了,Slaves 不停的从 Master 那里同步写操作,只是充当数据复制的机器而已, Slaves 没有有效的参与到分担负载的重任中来。所以为了能分担写操作的负载,这个时候需要做 vertical partitioning,把那些没什么联系、不需要 JOINS 操作的表分到不同的服务器上来减轻负担。比如,把一个用户的相关信息(photos, blogs, videos, polls, …)分散到不同的数据库服务器上,然后给每个分散的数据库里都配上1个带有重复信息的表(userids, nicknames, …),这个时候你仍然可以访问用户的相关信息或者按照要求执行 JOINS 操作。下面的图就是这种结构,Messages 和 Friends 配置成 Slaves,以便从 Top Maser 那里同步复制那些带有有用信息的表(userids, nicknames, …)

DB Setup 4: Vertical Partitioning / Replication Tree

把 DB Setup 2 和 DB Setup 3 结合起来就成了 DB Setup 4,只要负载过大就配一个或多个 Slaves 给服务器分担负载,这就成了下面的树形结构。

DB Setup 5: Hitting Limits

按照 DB Setup 4 不断深入到应用程序往下加 Slaves,到最后就会变得越来越困难,因为你不断 partition 数据库后你就会发现执行 JOIN 操作就会越来越困难,因为你分出了更多的表。有时候某个表可能会变得超级大以至于服务器处理不了,比如 Friendship 表(用来处理用户关系的表)增长得太快,如果只放在1个 Master 上太危险了,如果 Master 服务器 down 了怎么办?单个 Master 处理性能怎么样?你可以给服务器 scale up,购买更强大更昂贵的服务器,更快的CPU,更大的内存,不过总归不是个办法,迟早还会遇到瓶颈(DB Setup 5)。所以需要更好的 scale out 策略。

DB Setup 6:Sharding

DB Setup 4 的 vertical partitioning 已经帮了很大忙,但是网站继续增长流量继续增大怎么办? Master-Master 行得通不?Cluster 呢?这些方法都是为高可靠性和高性能设计的,对于现在这种需要分载写操作流量的情况不适合。Cache 呢?Cache 可以分担读操作流量,但是对于写操作不会有太大帮助。如果不能 vertical partitioning 了,那能不能 horizontal partitioning 呢?把 DB Setup 4 那张增长迅速、包含1亿条记录的巨大的表(Friendship)水平切成10份,每份1千万条记录,放在10个不同的服务器上。这种技术又可以叫做 sharding,被广泛用于大规模流量的网站上,如 Flickr, LiveJournal, Sun, Netlog 等。

上图把一个 photo 表 shard 到了10台不同的数据库服务器上。但是如何访问这些不同服务器上的数据呢,怎么能知道某个数据放在哪个服务器上呢?用一个小算法(userid % 10),只要知道了用户 userid,就可以知道用户的 photo 放在哪个数据库服务器上,然后连接那台数据库查询。

举一个简单例子,创建一个巨大的 photo 表,其中包含 photoid, title, description, dateadded, authorid,url 列,其中 authorid 是另外一个 user 表(userid, name, …) 的 foreign key。我们将把这张巨大的 photo 表 shard 到2台不同的数据库服务器上,用户 authorid 为奇数的就访问数据库1,authorid 为偶数就访问数据库2。

如果只有1台数据库服务器,不做 shard,访问数据库应该是这个样子:

<?php
$db = DB::getInstance();
$db->prepare(“SELECT title, url, description FROM photo WHERE userid = {userID}”);
$db->assignInt(‘userID’, $userID);
$db->execute();
$results = $db->getResults();

如果用2台数据库服务器来做 shard,我们需要传一个参数给 DB 类,以便 DB 类知道连接到哪个数据库,比如传 userID 给 DB::getInstance(),然后 getInstance() 计算 userID % 2 后返回数据库的连接信息:

<?php
$db = DB::getInstance($userID);
$db->prepare(“SELECT title, url, description FROM photo WHERE userid = {userID}”);
$db->assignInt(‘userID’, $userID);
$db->execute();
$results = $db->getResults();

Netlog 提到了 shard 数据需要注意的两点:

1、根据数据表的哪个列(如上面的 userid)来切分数据,使数据存到对应的数据库;
2、用什么算法来判断(如上面的 userid % 2)数据存到哪个服务器上。

如何根据数据表来切分数据主要依据程序来决定,Netblog选择的是用户 ID。以下有4种切分数据的方式可以参考:

1、Vertical Partitioning:如 DB Setup 3 那样;
2、Range-based Partitioning:如前1000个用户的信息存在服务器1,1001-2000存在服务器2,…;
3、Key or Hash based Partitioning:如上面的 userid % 2 的例子就是最简单的 key/hash;
4、Directory based Partitioning:最灵活的方式,把 key 和数据库服务器的对应关系保存下来,通过查找的方式找到对应的服务器。

DB Setup 7:Now

Netlog 在应用和数据库之间加了一个中间层,从 PHP 角度看有两部分组成,一部分是用来管理和维护,增加、删除、编辑 shards,数据库,lookup 系统;另一部分用来给数据库层和缓存层提供可以访问的 API。

Shards live in databases, databases live on hosts

Netlog 用的是方式4:Directory based Partitioning,用一个单独的 MySQL 表存放目录 lookup 信息,用来把 userID(shard keys)映射到对应的 shardIDs 上,然后通过一些配置文件把 shardIDs 映射到对应的数据库服务器上(得到相关数据库服务器的连接信息),以便后续操作在对应的数据库上执行。

举个例子来说明如何在 shards 上获取 userid 为26的 photo 信息 :

Query: Give me the photos from author with id 26.

Where is user 26?
User 26 is on shard 5 (26 % 10 -1).
On shard 5; Give me all the $photoIDs ($itemIDs) of user 26.
That user’s photoIDs are: array(10,12,30);
On shard 5; Give me all details about the items array(10,12,30) of user 26.
Those items are: array(array(‘title’ => “foo”, ‘description’ => “bar”), array(‘title’ => “milk”, ‘description’ => “cow”));

总结

“Don’t do it, if you don’t need to!” (37signals.com)
“Shard early and often!” (startuplessonslearned.blogspot.com)

作者在原文谈到了这两个看上去矛盾的观点。能不 shard 就尽量不 shard,因为 shard 会带来复杂性,数据库变复杂,服务器变多,难以维护、监测等。过分 shard 数据后,关系型数据库带来的好处就没了。尽量用简单的办法解决负载问题,比如:better hardware, more hardware, server tweaking and tuning, vertical partitioning, sql query optimization 等,如果这些能解决问题就不要shard。

另一方面,如果确定有 shard 的必要就要尽早开始设计,并且经常 shard,在设计数据库的时候牢记 shard 的两个关键点 sharding/partitioning key 和 sharding/partitioning scheme。

which property of the data (which column of the table) will I use to make the decisions on where the data should go?

And what will the algorithm be?

转载自:Netlog 的数据库及 LAMP 架构

Netlog 的数据库及 LAMP 架构的更多相关文章

  1. LNMP 与 LAMP 架构的区别及配置解决方案

    2014-12-31 10:33| 发布者: digitser| 查看: 5618| 评论: 0|原作者: liangsheng 摘要: LNMP 与 LAMP 架构的区别及配置解决方案 LNMP 的 ...

  2. Apache web服务器(LAMP架构)(week3_day4)--技术流ken

    apache介绍 1).世界上使用率最高的网站服务器,最高时可达70%:官方网站:apache.org 2).http 超文本协议 HTML 超文本标记语言 3).URL 统一资源定位符 http:/ ...

  3. 末学者笔记--apache编译安装及LAMP架构上线

    apache介绍 一.Apache的三种工作模式 Apache一共有3种稳定的MPM模式(多进程处理模块),它们分别是prefork.worker.event.http-2.2版本的httpd默认的m ...

  4. LAMP架构部署和动态网站环境的配置

    实验环境: 操作系统:centos 7.5 服务器IP:192.168.10.5 运行用户:root 连接工具:xshell工具 web环境:Linux+apache+php+mariadb(LAMP ...

  5. Apache web服务器(LAMP架构)

    Apache web服务器(LAMP架构) apache介绍 1).世界上使用率最高的网站服务器,最高时可达70%:官方网站:apache.org 2).http 超文本协议 HTML 超文本标记语言 ...

  6. LAMP架构上(一)

    第十七课LAMP架构上(一) 目录 一.LAMP架构介绍 二.MySQL.MariaDB介绍 三.MySQL安装 四.MariaDB安装 五.Apache安装 六.安装PHP5 七.安装PHP7 八. ...

  7. rhel6+apache2.4+mysql5.7+php5.6部署LAMP架构

    rhel6+apache2.4+mysql5.7+php5.6部署LAMP架构 2017年10月01日 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~准备阶段~~~~~~~~~~~~~ ...

  8. Linux LAMP架构搭建

    一.部署LAMP基本架构 1.L(linux)A(apache)M(mysql)P(php) 2.稳定版本(mysql5.1,php5.3,apache2.2) 3.安装顺序,mysql-->a ...

  9. 部署LAMP架构及其应用

    部署企业LAMP架构 (一)首先安装Apache服务,具体请见另一篇关于Apache的博文. (二)安装MySQL数据库,具体请见另一篇关于LNMP的博文. (三)构建PHP运行环境 1.安装PHP ...

随机推荐

  1. IntelliJ IDEA 的SVN配置与使用

    SVN 首先提一句,IDEA对各种的版本控制工具的支持是非常好的,点击3 打开系统设置界面,就可以看到他有专门的一栏 Version Control 里边是对各种版本控制工具的支持,其中我要用的SVN ...

  2. 自定义ConfigurationSection,创建多个嵌套的ConfigurationElementCollection节点

    由于接口地址都是固定的,所以想到使用自定义节点,来将接口都配置到web.config中. 很快,v1.0版本出炉: public class RequestConfigSection : Config ...

  3. Python入门笔记(26):Python执行环境

    一.python特定的执行环境 在当前脚本继续进行 创建和管理子进程 执行外部命令或程序 执行需要输入的命令 通过网络来调用命令 执行命令来创建需要处理的输出 动态生成Python语句 导入Pytho ...

  4. C#的Raw Socket实现网络封包监视

    同Winsock1相比,Winsock2最明显的就是支持了Raw Socket套接字类型,使用Raw Socket,可把网卡设置成混杂模式,在这种模式下,我们可以收到网络上的IP包,当然包括目的不是本 ...

  5. 重新想象 Windows 8.1 Store Apps (72) - 新增控件: AppBar, CommandBar

    [源码下载] 重新想象 Windows 8.1 Store Apps (72) - 新增控件: AppBar, CommandBar 作者:webabcd 介绍重新想象 Windows 8.1 Sto ...

  6. u-boot中nandflash初始化流程分析(转)

    u-boot中nandflash初始化流程分析(转) 原文地址http://zhuairlunjj.blog.163.com/blog/static/80050945201092011249136/ ...

  7. zeromq 学习和python实战

    参考文档: 官网 http://zeromq.org/ http://www.cnblogs.com/rainbowzc/p/3357594.html   原理解读 zeromq只是一层针对socke ...

  8. Gulp-前端进阶A-2

    1.js压缩 注意在根目录的package.json文件里在成功安装uglify后要有 "gulp-uglify": "^1.5.4" 才行 var gulp ...

  9. [TypeScript] 建置输出单一JavaScript档案(.js)与Declaration档案(.d.ts)

    [TypeScript] 建置输出单一JavaScript档案(.js)与Declaration档案(.d.ts) 问题情景 开发人员使用Visual Studio来开发TypeScript,可以很方 ...

  10. Backbone学习笔记一Backbone中的MVC

    原文章地址http://bigdots.github.io/2015/12/01/Backbone学习笔记(一)/#more Backbone.js为复杂WEB应用程序提供模型(models).集合( ...