代码改变世界

【转】distributed key-value database

2011-11-16 20:18  shy.ang  阅读(451)  评论(0编辑  收藏  举报

http://blog.gslin.org/archives/2009/07/25/2065/

资料库

RDBMS提供了很多而且很丰富的操作方式,但当资料量愈来愈大时,会遇到单台机器的网路频宽有限以及空间有限。这时候一定得走向多台的架构。

Replication

最容易解决的情况是「读取的query 比写入的query 多」,可以用database replication 解决,这也是Web 1.0 网站常见的解法之一(另外一种常见的解法是使用静态档案,或是reverse proxy cache),同步将资料复制到多台。

Memcached

接下来会发现当slave过多时会造成每台记忆体内重复cache相同的元素,也就是说,有二十台slave,每台都有SELECT * FROM `user` WHERE `name` = 'gslin'的结果其实很浪费资源。不过这个问题可以用memcached或是hash selection解决。

Sharding

在Web 2.0的环境里,User generated content成为主流,当写入的query超过单台可以负荷的量时,replication的架构就不是很适合了,因为每个写入的query在其他台slave上也会被执行。在商用资料库的领域通常是使用cluster架构,在open source领域的MySQL cluster也是cluster-based solution,不过用的单位还不是很多,而且overhead还蛮重的。

比较常见的解法是sharding:依照id,把资料拆散到各台。像是Flickr就是这样使用。

但sharding 就会少了很多RDBMS 可以用的特性(JOIN 与transaction),在写application server 或是library 的时候得花功夫多下几次query,并且注意资料的正确性。

上面这些方法在2005年Brad Fitzpatrick ( LiveJournal founder、memcached作者)的投影片「LiveJournal's Backend: A history of scaling」都有提到。

Sharding 是一个解法,但有不少缺点:

  • 需要application server 或是library,否则3rd party 程式得清楚知道sharding 的架构,才会知道资料要到哪个cluster 找。
  • 无法随意使用JOIN及transaction。如果真的要JOIN,设计时要想办法把需要JOIN的资料放在同一台database server。如果要跨机器transaction得透过2PC甚至3PC (看需求),或是类似的distributed transaction protocol,效能会比起同一台机器差很多。
  • 设计schema 时必须注意当一个cluster 愈来愈大时要rebalance,或是更进一步,在一开始设计时就考虑到资料搬移的问题。

Key-Value Database

后来就有不少人注意到,Web 2.0 网站很多时候不需要transaction,而JOIN 也会尽量避免。透过多次SELECT 拉资料,或是denormalize 以提高效能的方式还蛮常见。(JOIN 保证atomic,而且会因为query analyzer enginer 在没有正确分析的情况下会有大量的random access,比多次SELECT 耗资源)

另外一个是财务层面上的问题,一开始写的时候通常也都只有一组database server,不太可能一次就买两组database server。当成长到需要sharding 时通常写code 的人已经不只一个人,一定有人偷懒使用JOIN 或是其他无法sharding 的程式。这时候会发现需要「重写」而非「改写」。

于是就有人开始思考,如果我放弃RDBMS 的JOIN 与transaction,放弃到只剩下key-value 的架构,是不是有办法可以发展一套distributed database system 可以取得“incremental scalibility” 的特性(白话的说就是「加机器就可以增加承载量」),再想办法看看在这个系统上还可以加什么功能。

也就是说,这样的系统一开始可能只有两台小台的机器(为了HA),同时跑Web 与Database,当网站愈来愈大的时候我把这些小机器拉到前端跑Web,或是转为开发机使用,本来的Database 买15KRPM SAS (为了cache miss 的seek time 与latency) 与64GB RAM (还是为了cache hit 降低latency)。

所以在distributed key-value database 先有基本的功能:

  • GET(key)
  • SET(key, value)
  • DELETE(key)

有了这三个功能,至少你可以把本来在RDBMS 里很大一部份放到Key-Value Database 里。以Blog 来说,可以把所有的标题及内文部份放到Key-Value Database 内,大幅减少RDBMS 的cache 负担。

或者,key是path + filename,value是档案内容,当作一个filesystem在用。(也就是Amazon S3 )

这样对于前端写程式的人就会简单许多。整个Key-Value Database 是一朵可以无限扩充的云,前端程式不需要设计或是修改程式码就可以一直发展。如果当作Filesystem 就不用担心disk 满了之后加机器需要停机。

在这个想法下,就有许多单位投入资源往distributed key-value system发展。经过这些年的发展,分散式资料库主要有三个问题要解决,而且也被证明这三个问题无法同时解决(被称为CAP theorem,参考Brewer's Conjecture and the Feasibility of Consistent Available Partition-Tolerant Web Services, 2002这篇原始论文,或是参考比较简单易懂的说明「Brewer's CAP Theorem」):

  • Consistent
  • Availibility
  • Partition Tolerance

所以分散式资料库得在这三个条件内取舍。目前比较热门的Distributed Key-Value Database主要都是把Consistent放宽到“ Eventally Consistent “,只保证资料「迟早会一致」,这些Database包括了HBase ( Yahoo! )、Cassandra ( Facebook )这两套Java-based分散式资料库。

要了解这两套系统的架构,一般建议从「Amazon's Dynamo」这篇开始看,看完后再看这两套系统的系统架构介绍,以及mailing list的讨论。

这两套除了基本的Key-Value 外,还多了Column 的观念,弹性会比Key-Value 好一些。Yahoo! 与Facebook 都拿这个系统当Search Engine 使用。

另外有一些比较单纯的分散式系统,只有Key-Value而没有Column的,在「My Thoughts on NoSQL」这篇文章里对CouchDBRedis自称distributed的嘴炮批评了不少。另外「Anti-RDBMS: A list of distributed key-value stores」介绍了很多。

大致上是这样。