接上文。html
Cache Money虽然解决了数据的读取性能瓶颈;但开发大网站数据库面临的问题远不至读压力。mysql
首先是容量。算法
上千万/亿的数据量并不罕见,单一物理数据库服务器即使单纯承担写压力也会是瓶颈。更况且Cache Money仅仅是在理想情况下才能够作到数据库0读。缓存服务器更新,新增查询,复杂查询等等都还会形成读压力。sql
比较常见的作法是采用分表,也就是所谓的Sharding,把数据按照必定的规则,分别存储至多台数据库服务器上去。数据库
其次是变更。缓存
业务需求是不可预测的;不管一开始数据库表结构定义得如何完备,总会有新需求出来,须要对表结构作调整才能够实现。服务器
数据量过了百万以后,每次对生产服务器作alter table/create index等调整都是痛苦的经历。数据结构
针对容量与变更这两个问题,FriendFeed提出的schema-less database design给出了一个至关漂亮的解决方案。app
强烈推荐阅读FriendFeed的原文。less
FriendFeed的方案大体是这样:
FriendFeed的方案至关聪明,数据自己结构及其简单,sharding很容易作。写/读压力一会儿就分布出去。
blob列用于序列化(数据甚至是先zip过再存,CPU强劲,磁盘IO是瓶颈),因此结构能够随时变化;只须要保证序列化算法能够兼容不一样版本便可。
而灵活的序列化,偏偏是Facebook Thrift所解决的!
(还记得一开始使用Memcached作object cache时采用了Thrift作序列化么?)
先不考虑Sharding分布方案,在MoSonic中将各个类定义为相似下面的结构:
之后要修改数据结构,直接改Thrift的定义文件,而后从新生成代码就成。properties列中存的数据可能跟最新的结构不一直,但Thrift并不要求严格的匹配(BinaryFormatter则否则),它会自动忽略那些不符合的列;而一但Object被从新存入,数据就又会被从新序列化完整。
======================
FriendFeed的分布式方案要求表主建是uuid,而cache money却要求全部表必需要有自增的ID主健。
这其实不是冲突,把database_name + table_name + id当作一个uuid便可。
而FriendFeed的分布式索引,跟cache money中Vector Cache有殊途同归之妙。
都是根据查询条件作处理/sharding。
以前为MoSonic添加Vector Cache,已经须要判断查询的表名/查询条件;符合即查询缓存;这里套用FriendFeed的方案则变成,符合即查询分布式索引!
执行select id from users where age=18 limit order by id desc 0,10时
逻辑变成这样:
插入数据时,以前仅是更新Vector Cache,如今则需多一步去插入索引表。
实际运行中,由于是先插入数据表,同步更新Vector Cache,后续的插叙已经会命中缓存;索引表的更新实质变成是备份,能够异步插入。
Thrift / Cache Money / Schema-less Database Design其实是三个不一样团队为了解决不一样方面的技术问题而作出的方案,但糅合进MoSonic中时,我感到的不是冲突,而更多的是一种不谋而合的美妙。
下篇会继续讲更多一些细节。