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)