App数据层设计及云存储使用指南

作者:reganxie

 

引子:

  随着腾讯开放战略的实施,越来越多的第三方应用,伴随着开放平台迅速成长。在应用从小到大的发展中所遇到的各类技术问题里,涉及数据层的问题可以说是最棘手、最难解决的方面,特别是在应用进入产品高峰期时,海量用户会带来很多设计初期难以现象的访问压力。

  对于不涉及到数据的接入层或者逻辑层来说,遇到问题或者故障能够较快的进行定位和解决。但是对于数据层来说,由于数据状态的存在,以及对数据安全及可用性的要求,一旦出现问题,恢复时间可能非常长,影响深远。

  对于开发者来说,如果选择自行解决数据层的问题,那么在后期其花费精力可能会达到其他方面的的数倍之多,这简直就是一个梦魇。因此,本文结合我们所看到过的应用开发的主流过程和经验教训,针对数据层的技术解决方案进行了探讨和分享,并就如何应用云存储进行快速开发提出了一些建议。文中所述观点,仅为一家之言,不代表腾讯官方观点,谨供参考。

 

第一部分:App开发中的数据之痛

  根据我们对APP开发者研发过程的观察,面向数据层的解决方案大致有以下几个步骤:

1、直接使用单机Mysql来解决数据层的问题

  大部分开发者最初直接用Mysql,因为这个阶段应用开发的主要矛盾并不是性能压力、容灾等方面,而是如何快速的实现功能和上线。而业界流行的LAMP架构具备上手快的优势,这时的数据层直接用单机Mysql就搭建起来了。

1好处Mysql是一款非常知名的开源数据库软件,它功能丰富的、工具齐全,由于在全世界应用得非常广泛,基本上遇到任何问题都能够很快的找到讨论者和解决办法。同时在应用发展的早期数据库压力小,除了提供在线服务外,数据库往往还可以用来进行数据统计和经营分析。

2不足:数据库需要专职的DBA管理人员进行维护工作(如数据备份、主从切换等),对于外部开发者来说,往往是开发人员兼任DBA的角色,风险固然有,但由于设备数量少,一般不会出现大问题。只是偶尔的设备故障、软件配置不当和Bug等问题,对应用会有影响,但总体上能够承受。

2、 使用Memcached来分担读压力,使用Mysql来进行持久化

  应用接入开放平台后,用户会增长非常快,整个系统迅速地要接受新的考验。Mysql主要利用本机内存进行缓存,受单机物理资源限制,难以胜任并发读写较高高的应用场景,而很多Social Game都有同时高并发读写的特点,这时会发现应用响应速度明显变慢。

  这种情况下常见做法是在DB层之前加Cache,目前最常用的Cache就是Memcached,通过增加Cache设备和简单改造,可以快速上线。现在的数据层方案变成了Memcached缓存+Mysql持久化。Memcache应对读请求,Mysql应对写请求,效果立竿见影,DB压力迅速降低。

1好处MemcachedMysql一样,也是一款业内知名的开源软件。它具有接口简单、运行稳定、配置方便、性能出色的特点。

2不足:又多了一个模块需要开发者自己运营。而Cache层机器如果出现问题的话,可能会导致缓存丢失,命中率大幅下降,一旦出现这种DB层就非常危险,很容易产生严重的雪崩效应,恢复非常困难。另外,由于Cache只能用于应对读的压力,解决不了高并发写的问题,这个才是Social Game发展过程中最让人头疼的问题。

3、使用分布式MemCached和分库分表的Mysql集群方案

  单机的MemcachedMysql眼看着抵挡不住日益上升的访问压力了,开发者心里是有喜有忧,喜的是应用得到了用户的喜爱,忧的是要命的数据层又要面临严峻压力。既然发展到这个地步了,对数据层进行适当重构是必须的,业界关于分布式的方法可以借鉴的甚多,很多MemcachedSDK库已经支持分布了,Mysql也有分库分表的设计办法。经过一段时间的代码重构和数据搬迁后,数据层已经是个分布式的了。

1好处:现在的系统能够具备初步了较好的扩展性,可以根据用户活跃和访问情况进行扩容,用分布式的问题解决了单设备读写能力受限的困难。

 

2不足:虽然实现了系统的可扩展,可这并不意味着我们可以高枕无忧了。应用需要密切关注各服务的容量。对于Cache层来说,机器死机、扩容操作会导致缓存丢失,带来命中率大幅下降,而一旦DB压力过大,可能很长一段时间都缓不过劲来。而DB层的容错和扩容更是是令人神经紧绷,主备切换需要人工干预,还需要前端修改数据库接入IP、进行授权等若干配置;而扩容和数据搬迁操作一般只敢选在夜深人静的时候进行,一旦发现问题也要顶着巨大的压力去回滚和恢复数据,更是容易忙中出错。除此此外,要不要提前准备足够的资源也是令人十分纠结,准备多了会浪费资源,准备少了可能又满足不了业务的快速发展。而且Social Game的生命周期相对较短,往往数周之内迅速达到用户峰值,需要频繁的数据扩容和迁移,吃掉大量设备资源,接着就步入稳定和衰减期,又需要数据的合并和资源推出,对资源供应的要求非常高。而且此时的设备多,维护更加复杂,把如此庞大的精力都投在数据层显然是不明智的。

  其实,我们可以活的更好的!

4、使用CMEM云存储解决方案

  由于Social GameSNS特性,App在拥有一定的用户规模后,数据量大,读写请求非常多,读写比接近,大量的写到数据层,数据层由于IO原因抗不住写压力。针对这类情况和腾讯在数据层研发过程中的实际经验,我们目前提供了两款高性能、低成本的云存储产品,分别是:

1NoSQL的云存储产品:CmemCmem提供极高的并发读写能力,作为一款云存储产品,对用户透明的实现了自动容错、平滑扩容、数据备份、资源复用等一系列存储层的必要功能。将在线数据以Key-Value形式存放和访问,解决了大并发读写和令人头疼的数据层管理问题。

  CMEM的介绍和相关讨论请见:

http://yun.tencent.com/bbs/forum.php?mod=forumdisplay&fid=2

  CMEM全称为Cloud Memory Storage,是腾讯提供的高性能内存级持久化存储服务。

  CMEM基于一个存储键/值对的hashmap,具备内存级别的访问性能,并保证数据的持久性。

2SQL的云存储产品:CDBCDB是兼容Mysql协议的云存储产品,以实例的方式进行Mysql数据库的供给,并将数据迁移、实例扩容、数据备份等工作都放在了云中,对逻辑层透明,减少了开发者对于DB层的维护成本。

  CDB的介绍和相关讨论请见:

http://yun.tencent.com/bbs/forum.php?mod=forumdisplay&fid=36

  CDB全称为Cloud Database,是腾讯提供的分布式数据存储服务。

  CDB提供了高性能,高可靠的MySQL 集群服务,并且整合了备份,扩容,迁移等工具。

这个时候的设计模式是,将大量需要在线高效访问的数据通过Key-Value的形式放在Cmem中,将少量需要SQL功能的数据放在CDB中。

1好处Cmem完全兼容memcached协议,CDB兼容Mysql协议,这样对于开发者来说基本无门槛。在开发和运营过程中,开发无需关心存储层的数据安全、容错、扩容,这些问题全部在云端解决。

2不足CmemKey-Value存储,用于应对在线数据的实时高效访问,不具备传统SQL存储的一些常用功能,如实时统计、分析等。但实际上,大部分应用在使用Mysql作为存储层使用的时候,基本上也都是同时只对一条记录进行操作,这正式Key-Value的使用场景。如确实有SQL要求并且数据量适中、性能要求不高的数据,可以使用CDB解决。

第二部分:云存储——数据层解决方案

  看过应用开发过程中存储层方案变迁后,回到项目起始阶段,如果在应用开始设计时就考虑使用云存储来解决数据层的问题是非常明智的。一来可以快速开发,使开发者更加聚焦于应用逻辑开发和产品运营;二来减少数据层后期扩容、运维成本,减少故障概率。我们再从各个纬度来全面看下数据层是否使用云存储的优劣。

 

自行设计和解决数据层问题

使用CmemCDB等云存储方案

开发门槛

熟悉LAMP架构和业界知名开源软件如MemcachedMysql即可

Cmem兼容MemCached协议

CDB兼容Mysql协议

无门槛

研发效率

需投入专业人员进行数据层的设计和开发工作

无需关注数据层具体实现,通过云存储解决数据层性能、容量、安全及可用性问题,资源可投入到应用开发

运维质量

1、数据层开发要求高,设计时的疏忽可能带来运维中的重大数据灾难;

2、经常的重构和各类数据运维操作带来额外风险;

3、业务极速增长带来资源的压力,经常会导致系统过载

1、成熟可靠的存储层方案,保障数据安全和可用性;

2、全面的监控告警、自动容错机制;

3、云端资源池共享,支持业务的极速成长

运营成本

1、以实际设备投入来计算,即便只用了1/10的资源;

2、需提前准备资源来应对可能的业务突发;

3、业务开发人员兼顾数据层优化,性能提升有限

1、以实际使用资源来核算;

2、云存储资源的复用,资源单位成本小于直接使用物理资源;

3、专业数据层研发团队,从应用到硬件的极致优化

                                                          1

  可见,无论从性能、效率、质量、成本各个方面来看,对于第三方开发者来说,云存储都是更优的选择,不过这里还是有些研发模式的转变的。这一部分将就如何在云存储下进行数据层的设计进行一些分享。

  我们分析了App常用的数据类型、场景和访问情况,有一些基于Key-ValueApp数据设计参考方案供参考。目前对于各类应用来说,所用到的主要数据类型大致有以下几种:

 

数据类型

示例

数据量

读取量

修改量

1

用户资料

昵称、等级、金钱、经验

2

背包数据

农场游戏的田地、果实等

3

Feeds

“小明摘了我的菜”

“小白帮我捉了虫”

4

留言信息

好友留言、系统消息

5

购买物品

用户装饰、游戏道具

6

成果归档

某用户升级到30

7

其他

好友排名、游戏排名

                                      表2

  除了第7点的排序工作外,通常应用对各类数据的在线访问都是以Key的形式来访问Value,并不会用到SQL功能。比如用户经验值成长了,我们根据用户id取出用户资料,修改经验值并设置回去就行了。特别是前几类高访问量的数据,非常适合Cmem的高性能存储场景。同时,将不同类型的数据分开存放在不同的数据表中是有好处的,同类数据的局部化可以方便Cmem根据不同模型进行更好的优化。

 

  那么有没有场景是涉及到多条记录操作的,答案是有。比如农场游戏中A摘了好友B的萝卜,A的数量要增加,B的要减少,就涉及到多个记录的修改了。这个时候在分布式场景中如果要使用事务是极其不理智的,即便能实现(没有分库分表),在实际使用的性能消耗也非常高,基本上不可承受。其实上是有折衷的方案的,比如先增加A的数量,再减少B的数量,这时出现问题的概率非常小,而且出现了也不会影响游戏效果和用户体验,但换来的却是系统扩展性和性能的大幅提升。在实际使用中,有的应用自己简单实现了一个非常轻量的transaction模块,效果也非常好。

 

  针对表2中的各类数据类型,我们给出了建议使用场景,这里主要是根据访问密度和数据量2个纬度来衡量(Cmem具备更高的性能和扩展性,CDB提供SQL支持),下表中访问密度高表示>500iops/GB数据量高表示>150GB

访问密度

数据量

推荐云存储方案方案

示例数据

Cmem

背包数据

Feeds

Cmem

用户资料

Cmem(数据量有持续增长的需求)

成果归档

CDB(数据量相对固定且有SQL的需求)

好友排名、用户排名

CDB

购买物品

留言消息

                               表3

  根据上述一些原则,结合实际的应用策划,如果在早期能合理的进行数据层的规划,那么就可以避免在后期遭受巨大的数据层运营挑战。那么,CmemCDB能解决所有的数据层问题吗,显然它们不是万能的,不过它们能解决我们目前在线上业务中最棘手的在线数据访问的根本问题。解决了这个,其他问题都好办了。如果还有什么疑问,请访问yun.tencent.com,那里有更多的信息和解答。

第三部分:应用云存储的一些遗留问题

1、事务操作

  应尽量通过业务逻辑来避免事务,在Social Game开发中使用事务是极其不明智的行为,当然支付类操作除外,不过这个不属于游戏数据的在线访问,腾讯云平台也提供了相应的解决方案;

2、统计分析

  提供数据导入到DB的功能,但DB分析能力终归是有限的,计划日后提供类似MapReduce原理的分析工具;

3、游戏运营

  比如需要对金钱<100的用户统一送2000金币,如果碰到这类问题,分析系统+操作工具应该是个不错的选择,直接去数据库修改太危险了,不是吗?

4、用户排名,搭建额外的排名系统,效率更高

  设计个专用的排名系统把,逻辑实现即可,既高效又不影响在线数据的访问。