crazyjohn / crazyjohn.github.io

crazyjohn's blog
9 stars 3 forks source link

mysql 存储方案演变 #21

Open crazyjohn opened 9 years ago

crazyjohn commented 9 years ago

游戏中我们经常会选用mysql作为存储方案,那么如何一步步优化以及演变让它可以适应各种游戏类型/业务的承载需求。

0.0 架构演变图

这个图是存储结构的一个演变图,那天和jiachun讨论DB层的承载设计的时候也在黑板上画过这个图。我简单说一下:

  1. 首先是最简单的结构,逻辑层和数据库之前有一层数据层DataLayer,数据层用来封装对数据的读写访问。
  2. 对上头的架构进行优化,降低读的压力,使用在数据层内部内置一层数据缓存,使用预加载以及LRU之类的策略来大大降低读压力。
  3. 在上头结构的基础上再次进行优化,把DB那里的读事件和写事件拆分开,也就是所谓的读写分离,使用master-slave结构,写事件只发送到master,然后读事件发送到slave,mater和slave之间要进行sync数据同步操作。
  4. 进一步优化上头结构,提高承载。对master-slave结构做多个cluster实现scale out横向扩展。

    0.1 一致性hash

  5. 说一致性hash,首先要说的是横向扩展scale out。什么是scale out呢?它说的是当单机的处理能力达到瓶颈的时候,我们通过添加机器来达到提高处理能力处理量的目的。
  6. 举例来说单机处理的数据量是5条,那么理想情况下2台机器的处理量就是10条。那么问题也来了,如何在这2台机器上分布这10条数据?最简单的办法,我们可以使用数据的主键id去做mod模运算,算法也就是id % 机器数量,然后把指定数据分布到指定机器。再复杂一些比如id是string类型的话,可以通过:hash(id) % machineCount的方式。这样就可以按需工作了。具体些,假设id集合是(1,2,3,4,5,6,7,8,9,10),那么机器1分布:(1,3,5,7,9),机器2分布(2,4,6,8,10)
  7. 这时候需求又来了,随着业务规模增加我们出现了15条数据(apend 11, 12, 13, 14, 15),那么我们需要增加机器,变成3台。这时候数据需要重新分配:1号机器(1,4,7,10,13)2号机器(2,5,8,11,14),3号机器(3,6,9,12,15)。这时候出现一个问题就是数据迁移,数据完全被打乱了,目前这个规模迁移起来工作量还好,因为我故意缩减了规模方便理解,但是真实生产中,这个过程是致命的。
  8. 一致性hash来救场。做法是这样的,我们先虚拟出2的次幂节点,比如2的32次方这样,大概是42亿的节点,这个节点数肯定是可以满足绝大部分应用需求。然后机器的position通过:hash(nodeIp) % 虚拟节点总数。假设机器1:555,机器2:6666,机器3:88888。数据的分布方式也一样的算法,hash(id) % 虚拟节点总数,然后根据获得的值区间去落地到指定的节点。这时候如果数据规模要扩大,需要新加机器4,那么我们只需要把边界的数据进行转移,不会出现上面的大工作量移植的情况。