Sina App Engine数据存储服务架构

一、什么是Sina App Engine

Sina App Engine(简称SAE)是新浪研发中心于2009年上旬开始内部开发,并在2009年正式推出第一个Alpha版本的国内首个公有云计算平台(http://sae.sina.com.cn),SAE是新浪云计算(简称浪云)战略的核心组成部分。

SAE作为国内的公有云计算,从开发伊始借鉴吸纳Google、Amazon等国外公司的公有云计算的成功技术经验,并很快推出不同于他们的具有自身特色的云计算平台。SAE选择在国内流行最广的Web开发语言PHP作为首选的支持语言,Web开发者可以在Linux/Mac/Windows上通过SDK或者Web版在线SDK进行开发、部署、调试,团队开发时还可以进行成员协作,不同的角色将对代码、项目拥有不同的权限;SAE提供了一系列分布式计算、存储服务供开发者使用,包括分布式文件存储Storage、分布式数据库集群RDC、分布式缓存MemcacheX、分布式定时服务Cron、分布式异步队列TaskQueue、邮件服务Mail等,这些服务将大大降低开发者的开发成本。同时又由于SAE整体架构的高可靠性和新浪的品牌保证,大大降低了开发者的运营风险。另外,作为典型的云计算,SAE采用“所付即所用,所付仅所用”的计费理念,通过日志和统计中心精确的计算每个应用的资源消耗(包括CPU、内存、磁盘等)[1]

总之,SAE就是分布式Web服务的开发、运行平台。

附,SAE和传统的虚拟主机托管VPS的主要区别:

类项

SAE

VPS

核心用户

Web开发者

无核心用户

使用方式

服务使用

设备租用

目标

力争覆盖Web服务所有需求,提供多种服务给开发者使用

仅基本需求

SLA(服务承诺)

高可靠性及严格的服务承诺

依服务商变化,无严格协议

计费方式

所付即所用,所付仅所用

预付费,无精确计费

SAE在2009年11月3日发布了alpha1版本,2010年2月1日发布了alpha2版本,2010年9月1日发布了beta版本,截止到2011年4月30号,注册开发者已经接近10000人,活跃App接近3000个,每天独立代码部署行为超过3000次。

二、SAE的数据存储服务

众所周知,Web应用的最核心的是数据,数据对用户异常重要,对开发者本身也是最重要的信息。所以,保证用户和应用数据的可用性、可靠性、安全性就是云计算平台实现的重中之重。

Sina App Engine数据存储服务架构_第1张图片

SAE数据存储关系图

如上图所示,SAE作为Web计算中心通过Apache HTTP+PHP提供给用户Web服务,Web服务通过API调用SAE内置的各种服务和外置的第三方服务(图中所示仅为SAE官方内置服务的数据存储部分)[2]。服务分成两类:计算型服务Computing和存储类服务Storage。而计算型服务又分成同步计算服务(如FetchURL、Image等)和异步计算(如Cron、TaskQueue等)服务,而存储服务则分成非持久化存储服务和持久化存储服务,本文只针对介绍存储服务。

非持久化存储服务包括了传统意义上的缓存服务,它能够提供大并发和高速读写,但是不保证数据的完全可靠,也就是说,当发生系统故障时可能会发生数据丢失和不一致。按照功能非持久化存储分成了通用缓存和功能性存储,SAE上的MemcacheX就是通用性缓存,大家可以理解为LAMP架构中常见的memcached。计数器服务Counter和排行榜服务Rank属于功能性缓存,可以为特定场景下的需求提供更方便的服务,值得一提的是,计数器服务和排行榜服务的HA可靠性都比通用的MemcacheX高,具有一定的容灾和数据修复迁移能力,所以他们也兼有持久化存储的特性。

持久化存储服务用来存储用户需要落地的数据,这类服务强调高可靠性和高可用性,在分布式环境中以最终一致性来保证HA。持久化存储服务根据存储数据是否为结构化又分成两类:结构化数据存储包括传统意义的关系型数据库MySQL(在SAE中,以RDC提供)+NoSQL数据库(KV,在开发中)和非结构化数据存储(分布式文件存储Storage)。

从目前国内外流行的Web应用和网站看,MySQL和memcached是最重要的服务组件,MySQL提供实际数据存储,memcached提供高速访问缓冲,甚至有些游戏网站直接拿memcached当实际存储,然后定时将其中的数据刷到MySQL中实现落地。从Facebook、Twitter等网站的公开文档中,也都可以看到,memcached在其架构中被广泛使用,而且也没有放弃MySQL,MySQL仍作为其核心数据的存储服务。

所以,MySQL和memcached服务对应的RDC(Relational Database Cluster)和MemcacheX也是SAE的所有数据存储服务中最重要的组件,从实际的运维经验中也确实如此,像数据库的主从同步、缓存的失效和无法写入等问题都直接关系到线上应用的用户体验,所以本文着重介绍RDC和MemcacheX,了解了这两个服务,也就了解了SAE数据存储的核心。

三、RDC(Relational Database Cluster)

随着NoSQL概念的兴起,传统MySQL关系型数据库在云计算时代遇到了挑战,无论是亚马逊还是Google,在其云计算服务伊始都不约而同的避免了关系型数据库而主推其NoSQL数据库。但是,从AWS SimpleDB等服务的实际效果来看,普通开发者对于传统MySQL的依赖仍然十分严重。所以,出于降低开发者学习成本和迁移成本的考虑,SAE从一开始就确定了“不能放弃MySQL”,要对用户提供MySQL服务的目标,而这也就是RDC的设计和实现的初衷 。

对于RDC,用户可以简单的理解其为MySQL的中间层或者代理层,类似MySQL Proxy。所有的SQL请求都由RDC传递到后端的实际存储上。

RDC作为对外提供服务的数据库集群,具有和传统MySQL Proxy截然不同的目标和要求,那是解决公有云数据库集群的安全性,为用户提供的强隔离性,而这个特性是私有云计算平台上的数据库集群所不具备的。除此之外,RDC要求还具有对数据库的监控、管理功能,实时监控用户的DB的健康状况和主从同步延迟情况,一旦发现异常,将会在15秒内完成切换工作,用户的请求会被转发到其他正常的机器上。和某些私有云计算平台上的数据库集群提供的水平扩展和垂直划分不同,RDC不提供用户数据库水平扩展,而是通过提供以下两个地址:

w.rdc.sae.sina.com.cn:3307 => 写库(主库)
r.rdc.sae.sina.com.cn:3307 => 读库(从库)

由应用层自行处理,对于Sina App Engine上的开发者,其实可以使用PHP语言级的数据库类(SaeMysql)自动实现读写分离。

RDC从2010年9月开始完成设计并开始编码,到2010年底完成测试,其自身采用的是多进程非阻塞方式的通讯框架,自身性能消耗较少,根据内部性能测试,开启SQL cache时对比直接访问MySQL的性能损耗在5%以内。

RDC在2010年底正式上线,目前SAE上所有的数据库访问都通过RDC来提供,并且已经稳定运行了半年。RDC虽然为分布式数据库集群,但是对终端用户完全透明,用户在使用RDC时,不会感觉到和使用传统的MySQL数据库有任何差异,甚至用户都不用知道RDC的存在。用户可以使用所有MySQL标准客户端(MySQL5以上)操作RDC,如mysql_query、mysql_connect等,错误处理和标准MySQL客户端处理模式一样,用户操作RDC的示例代码:

$con=mysql_connect('w.rdc.sae.sina.com.cn:'.$_SERVER['HTTP_MYSQLPORT'],SAE_ACCESSKEY,SAE_SECRETKEY);
if (!$con) 
    die('could not connect: ' . mysql_error());
$sql = "SELECT * FROM Person";
if(!mysql_query($sql,$con))
    echo mysql_errno() . ": " . mysql_error() . "\n";

Sina App Engine数据存储服务架构_第2张图片

RDC整体架构图

RDC的整体架构如上图所示,开发者通过SAE StdLib(自动支持主从分离)或者标准MySQL PHP函数(手工访问w.rdc.sae.sina.com.cn:3307和r.rdc.sae.sina.com.cn:3307来控制主从分离)在SAE平台上调用RDC。当一条SQL语句到达RDC时,RDC先将其翻译解析,然后查看cache的解析结果,如果命中则根据结果做出判断(SQL预判,见下文),如果没有命中则送到后端(根据accesskey到DB的映射关系)进行判断。判断结果完成后,如果是拦截则直接返回用户MySQL Error并通过errmsg告知拦截原因,否则就进行正常的SQL访问。

RDC支持的数据库后端的数量为百万级,其自身设计为无状态结构,并且可以随时水平扩展(而后端数据库的水平扩展由用户自己负责),accesskey到DB的映射关系由SAE自身的支持分布式一致性的trigger服务保障。

RDC后端的DB为标准的MySQL一主多从结构,具体几个从库由用户级别对应的SLA决定(默认是两个从库),主从之间通过binlog做最终一致性保证。目前RDC上的MySQL的存储引擎为MyISAM,以后会支持InnoDB。RDC不支持非SAE环境直连,这里主要是因为用户客户端如果不在SAE的环境中就很难保证和数据库的网络状况。用户如果想管理数据库可以通过SAE应用页面里的PHPAdmin进行操作。

在编码实现上,RDC类似MySQL5(除去存储引擎部分),但在细节上和标准MySQL还是有几个显著区别:

  1. RDC采用多进程实现(SAE上的服务几乎都是多进程结构),而标准MySQL采用多线程
  2. RDC对SQL语句的解析是词法解析,而标准MySQL parser则是标准的语法解析,这样做的好处是词法分析更快,而RDC并不需要完整的挂接语义动作
  3. RDC的cache层在词法分析后,这意味着即使用户的SQL语句有些改动,比如多了1个空格,仍会命中cache;而标准MySQL的query cache[3]则在语法分析前,SQL语句即使多了1个空格,仍然会使cache失效

RDC自带一个监控进程,监控分成两部分:健康监控和主从监控。健康监控会定期连接DB,发现故障时,自动做切换。主从监控通过分析slave stat和binlog pos来确定主从延迟情况,发现高延迟时,将请求自动切换到低延迟的DB。RDC的监控还自带了网络状况检查和跨IDC配置,以支持跨IDC部署RDC需求。

安全性保证

安全性是RDC作为公有云计算数据库服务的最大挑战,试想,如果一个初学用户在上千万记录的表上执行不带where语句的select是什么后果,如果一个恶意用户故意频繁执行大量的join是什么后果。为了解决这些问题,RDC设计了三道“防护线”的策略来保护用户数据库的隔离性。

SQL预判机制

RDC会根据自身算法预先评估SQL语句的效率,当发现有可能是性能不高的SQL语句时,会对开发者做出提示(这在RDC内部叫软拦截),而当发现可能对整个数据库平台造成伤害的SQL语句时,会直接在RDC层将其屏蔽掉,并以标准MySQL的错误返回方式告知开发者。RDC会对以下几种语句做出预判:

select 
update 
insert 
delete 
replace 
create table 
alter table 
create index 

以最复杂的select语句为例,RDC的判断依据包括了:select语句是否带where语句、查询条件是否带了恰当的索引、是否带有子查询、是否带有连表join操作、子查询和join和主查询的关系、join和子查询的复杂度、是否有不恰当的排序、是否有limit限定等。
目前,该判断算法已经申请专利。

并发执行时间和

RDC率先提出这个概念,来取代传统MySQL的并发连接数限制,原因主要是因为传统的连接数限制较为粗鲁,不能区分用户,换句话说, 无法区分"SQL优化得好的用户"和"SQL执行性能低下的用户"。而并发执行时间和很好的解决了这个问题,
并发执行时间和=当前所有活的请求已经执行的时间和
举个例子,如果SQL并发执行时间和为10000ms:

A用户的平均每条SQL消耗100ms,那么A获得的最大并发为100

B用户的平均每条SQL消耗1000ms,那么B获得最大并发仅为10

并发执行时间和从技术层面突出一个产品引导:“对于SQL效率高的用户支持更大的并发,而SQL执行效率低的用户则可能不会获得大的并发”,以鼓励用户优化自己的SQL,优化自己的表结构,提高SQL的执行效率,减少对系统的消耗。

慢查询保护

MySQL自身会产生慢查询日志,正常应用的慢查询肯定不会超过一定额度,那么超过这个额度我们就会给出建议和报警,如果应用超过慢查询系统上限,则可能导致MySQL服务暂时禁用(过十分钟会自动开启),以保护其他的数据库服务正常使用并督促应用的开发者尽快修改代码或作MySQL结构优化。

通过上面三种不同层面的策略,有效的保护了RDC的后端实际数据库。从实际运行效果看,98%正常应用并不会受到RDC SQL保护的影响,而%1的应用因为数据库设计编码经验不足而触发了大量的RDC拦截,用户可以在SAE日志中心实时的看到这些日志,日志中心还会针对这些日志给出MySQL优化改进建议。事实证明,通过RDC使SAE避免了多次重大数据库故障。

四、MemcacheX

传统的公有云计算平台的memcache服务,往往是给开发者提供一个类memcached的实例,用户可以自主使用其memcache而不影响其他用户的memcache。但这种实现有个致命缺陷:即当memcached实例出现故障时,会使应用全部缓存key穿透数据库,而很可能造成重大故障。除此之外别的缺点也不少,比如成本过大,每个memcached都有额外的内存overhead,从而浪费了不少空间,再比如扩容时必须重启服务,这样导致扩容会导致用户的key失效等等。

SAE MemcacheX服务设计和实现的目的就是克服上述缺点,代替现有的memcached服务,从而降低运行成本,并且为用户提供高可靠性的缓存服务。

Sina App Engine数据存储服务架构_第3张图片

MemcacheX架构图

从上图可以看出,用户通过标准memcache客户端使用MemcacheX服务,用户的key通过客户端的一致性hash分散在所有的MemcacheX节点上,这点和标准的memcached服务几乎一样,但不同的是每个用户的key加上了他们的应用名做前缀区分,这样多个用户的key可以共享一个MemcacheX实例,甚至共享同一套slab内存池,提高了内存使用率。每个用户都独立享有实例的统计信息和LRU信息,也就是说,当某个用户的memcache内存使用到了其申请的大小上限时,key只会和本用户的key做LRU交换,而不会影响其他的key。MemcacheX还对slab算法进行了改进,因为memcached的slab算法并没有伙伴系统[4]的回收逻辑,所以可能会导致在明明还有内存的时候,分配不成功,MemcacheX对此的改进有效的降低了这种可能性。MemcacheX支持内存自动扩容,扩容过程不用重启服务,所以用户无需担心扩容后的穿透问题。

因为每个用户的key都会被一致性hash在所有MemcacheX的N个节点上,所以当某个节点出现故障时,理论上只有1/N的key受到影响,而当N足够大时,就不会对用户的应用造成致命影响,从而提高了HA。

MemcacheX还具备一个功能,就是connection LRU保护。新浪动态应用平台的实际运维经验表明,因为系统的不可靠性和Web开发人员代码质量的不可控性,传统memcached容易造成连接资源耗光的的情况,比如下面的代码:

$memcache_obj=new Memcache;
$memcache_obj->connect('memcache_host',11211);
if($memcache_obj->get('key')!=false)
do_mysql_query()
$memcache_obj->close();

试想,当数据库操作do_mysql_query()因为某种原因阻塞住时,该代码就会造成memcached的连接资源没能及时释放,当并发访问量很大时,可能造成瞬间memcached文件描述符资源耗尽,从而影响服务,即使当数据库恢复正常时,memcached仍然不可用。

MemcacheX的connection LRU就是解决这个问题的,connection LRU是指当极端情况下的连接资源耗尽时,可以淘汰旧的连接以保证可以正确建立新的连接。这样做固然会影响某些应用的正常逻辑,但可以在特殊时期保证新用户的正常使用。

2011年3月,MemcacheX已经在SAE上线。经过测试和实践检验,MemcacheX和传统memcached拥有同样的性能,并且具有更高的可靠性。

通过RDC和MemcacheX,SAE很好的支持了近万开发者的数据库和缓存服务,RDC每天请求量超过6000万,MemcacheX的每天请求量则超过1亿,两者共同承担了90%以上数据读写需求,也正是因为这两个服务,才保证了公有云计算平台上的用户数据读写的可用性和可靠性。另外,除了RDC和MemcacheX,Sina App Engine技术团队近期还研发了很多重量级产品[5]:支持系统层文件排重的分布式强一致性文件部署系统CodeFS、计数器服务Counter、排行榜服务Rank,以及正在开发中的分布式NoSQL存储SAE KV。对于这些服务的架构和技术细节,我会在以后的文章和大家分享。

欢迎使用SAE:

  1. Sina App Engine注册页面,http://sae.sina.com.cn/
  2. Sina App Engine体验账号申请页面,http://sae.sina.com.cn/?m=home&a=exp
  3. 微博开发平台SAE账号申请页面,http://open.t.sina.com.cn/apps/new

参考资料:

  1. Sina App Engine架构-云计算时代的分布式Web服务解决方案
  2. Sina App Engine-deep inside cloud service
  3. MySQL query cache
  4. Buddy System
  5. SAE服务总体说明

你可能感兴趣的:(Sina App Engine数据存储服务架构)