MoSonic:对SubSonic的分布式存储、缓存改进尝试(2)

上文html

Cache Money真正牛X的地方是在Vector Cache。在生产环境中,它不只相对Object Cache命中率较更高,带来的性能飞跃更是可观。java

在MoSonic的性能测试中,获得了有10倍的性能提升。web

Vector Cache性能恐怖,但它对表结构,查询类型,有至关的严格的要求;列举以下:算法

  • 表必须以自增数字(int / long)id为主键
  • 查询的where中必须是 = 等于条件,如where user_id=1
  • 多个where条件的话,相互关系必须是And,如where user_id=1 and id_deleted=0
  • 查询结果仅能是数据id,如 select id from users where ... 不能够是 select user_name from users where ...
    • 也能够是 select count(*) from users where ...
    • 查询结果支持分页
  • 查询结果必须以id排倒序,也就是order by id desc

只有彻底符合上面五个条件,Vector Cache才能够生效;幸运的是,在web 2.0网站中,这类结构/查询正好是最多见的。数据库

以博客为例,博客文章列表显示,分类文章数量,评论显示等等,基本都符合上述的查询。缓存

比方说,要得到等级为1的用户时,须要使用下面的两个查询:ruby

 

  • select id from users where level=1
  • select * from users where id in (....)

 

两个查询cache money均可以彻底缓存,若是直接使用:架构

 

  • select * from users where level=1

 

的话,cache money则会彻底失效。并发

对于两种风格的查询孰优孰劣,能够参考JavaEye老大Robin以前写的:为何ORM性能比iBATIS好数据库设计

=============

由于要求了查询结果必须是id,而且排倒序,Vector Cache其实是能够作到实时自动更新,而不是自动过时。

考虑这样的调用:

 

  1. select count(id) from photos where album_id=1 order by id desc limit 1, 100
  2. select id from photos where album_id=1 order by id desc limit 1, 100
  3. insert into photos (album_id)values(1)
  4. select count(id) from photos where album_id=1 order by id desc limit 1, 100
  5. select id from photos where album_id=1 order by id desc limit 1, 100

 

显示列表,插入数据,再次显示列表;这是至关典型调用。

第1/2步查询会有缓存(即使是没有缓存,查询以后,缓存也会自动被生成,也就是所谓的直读)。

第3步插入数据时,得到数据库自增的ID后,能够直接将此id追加到第1/2步查询缓存结果中。

第4/5步查询直接命中第3步写数据时更新的缓存;彻底无需查询数据库。

在查询、应用场景符合的理想状况下,有了Vector Cache,数据库读能够变成恐怖的0读取

数据库仅须要承担写压力,100%的读都有Memcache的自动缓存。

这才是Cache Money的Vector Cache带来读性能飞跃的缘由。

全部的数据库查询都变成了memcache get;memcache单机时在读能力,并发负荷能力上都要比传统关系型数据库高一个数量级;并且其shared nothing的架构,又能够水平扩张。

在高并发,多机缓存的状况下,能够预料Cache Money带来的读性能提升远不止10倍。

==============

Twitter的工程师对Cache Money的实现至关巧妙,他们针对一个限制多多的场景作到了100%的读缓存;而这个“限制多多”又偏偏是web 2.0网站中的最典型场景。

我在MoSonic中实现Vector Cache时,彻底照搬了Cache Money的实现算法;就是C#的代码量比ruby膨胀了几倍。

:)

下篇会继续讲MoSonic对FriendFeed分布式数据库设计的引用。

相关文章
相关标签/搜索