MySQL 单库后期分库策略


用户中心是单库单表,uid使用数据库自增主键,uid被很多业务关联,不能变化。当用户中心数据量逐步变大,如何由单库升级为多库呢?

    很多公司都会利用数据库“插入数据自动自增id”来作为业务id,这种方法会使得业务与id生成强耦合,导致id生成算法难以升级。现在我们来了解一下ID生成要考虑哪些要素。


【ID生成要考虑的技术点】

    几乎所有业务,都会有一个业务唯一标识:

        用户标识:uid(user-id)

        消息标识:mid(msg-id)

        订单标识:oid(order-id)

    这个标识,在存储系统里通常是主键,主键使用聚集索引(clustered-index),即在物理存储上以这个id排序。于是,对这个id有:唯一性,趋势递增性的要求。

    这个标识,也经常被用来做流量负载均衡,数据负载均衡的依据,即这个id必须在统计上必须是完全随机的。于是,对这个id有:随机性的要求。

    同时,id生成算法升级,理论上对业务系统是透明的。于是,对这个id的生成有:独立性需求。

    为了保证id生成的上述特性,要有一个:

        uint64_t GenID()

    的独立方法(或者独立接口)来生成id,生成id具体做什么用,该方法不关心,可以是用来做uid,也可以是用来做oid,甚至log-id。

    当然,id生成的具体细节,业务也不用关心。即,GenID()的内部实现,可以是利用数据库的自增id,也可以使用时间递增,目前行业内最流行的,是仿照snowflake生成分布式id。

    这个封装,屏蔽了id生成的细节,保留方案升级的可能性,是系统设计中,解耦的体现。 

    如果使用了此类方法生成业务id,数据库由单库扩展多库就很容易了:

        (1)确定一个路由算法,例如hash取模;

        (2)将单库中的数据,通过这个路由算法迁移到多库中去,以实现单库数据量的减少;

        (3)通过这个路由算法寻找数据(读);

        (4)通过这个路由算法插入数据(写);

    假如架构设计前期没有提前考虑独立的id生成,后期又要实施单库拆多库,该怎么办呢?


【如何将单库拆解为多库】

    假设由单库拆分为3库,可以这么玩:

        (1)做一个1主2从数据库集群,相当于每条数据复制成了3份;

        (2)将路由算法,设为取模hash算法,%3;

        (3)第一个库,%3=0,把余1和余2的uid删掉;

        (4)第二个库,%3=1,把余0和余2的uid删掉;

        (5)第三个库,%3=2,把余0和余1的uid删掉;

        (6)将每个库的自增步长设置为3,这样每个库的id生成就不会重复了;

        (7)升级用户中心,按照路由算法查询uid数据;

    搞定,拆库扩容达成:

        (1)单库数据量下降为了原来的1/3;

        (2)读写实例个数扩充为了原来的3倍;

        (3)并且id生成与查询都不会冲突;

    希望各位以后能提前考虑到id生成的唯一性、随机性、趋势递增性、独立性。


上一篇

评论

登录后可发表评论


:
09月05日 11:54
。。。。。。