zoukankan      html  css  js  c++  java
  • MySQL分库分表环境下全局ID生成方案

    在大型互联网应用中,随着用户数的增加,为了提高应用的性能,我们经常需要对数据库进行分库分表操作。在单表时代,我们可以完全依赖于数据库的自增 ID来唯一标识一个用户或数据对象。但是当我们对数据库进行了分库分表后,就不能依赖于每个表的自增ID来全局唯一标识这些数据了。因此,我们需要提供一 个全局唯一的ID号生成策略来支持分库分表的环境。下面来介绍两种非常优秀的解决方案:

    1. 数据库自增ID——来自Flicker的解决方案

    因为MySQL本身支持auto_increment操作,很自然地,我们会想到借助这个特性来实现这个功能。Flicker在解决全局ID生成方 案里就采用了MySQL自增长ID的机制(auto_increment + replace into + MyISAM)。一个生成64位ID方案具体就是这样的:
    先创建单独的数据库(eg:ticket),然后创建一个表:

    CREATE TABLE Tickets64 (
                id bigint(20) unsigned NOT NULL auto_increment,
                stub char(1) NOT NULL default '',
                PRIMARY KEY  (id),
                UNIQUE KEY stub (stub)
        ) ENGINE=MyISAM
    

    当我们插入记录后,执行SELECT * from Tickets64,查询结果就是这样的:

    +-------------------+------+
    | id                | stub |
    +-------------------+------+
    | 72157623227190423 |    a |
    +-------------------+------+
    

    在我们的应用端需要做下面这两个操作,在一个事务会话里提交:

    REPLACE INTO Tickets64 (stub) VALUES ('a');
    SELECT LAST_INSERT_ID();
    

    这样我们就能拿到不断增长且不重复的ID了。
    到上面为止,我们只是在单台数据库上生成ID,从高可用角度考虑,接下来就要解决单点故障问题:Flicker启用了两台数据库服务器来生成ID,通过区分auto_increment的起始值和步长来生成奇偶数的ID。

    TicketServer1:
    auto-increment-increment = 2
    auto-increment-offset = 1
    
    TicketServer2:
    auto-increment-increment = 2
    auto-increment-offset = 2
    

    最后,在客户端只需要通过轮询方式取ID就可以了。

    • 优点:充分借助数据库的自增ID机制,提供高可靠性,生成的ID有序。
    • 缺点:占用两个独立的MySQL实例,有些浪费资源,成本较高。

    参考:http://code.flickr.net/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/

    2. 独立的应用程序——来自Twitter的解决方案

    Twitter在把存储系统从MySQL迁移到Cassandra的过程中由于Cassandra没有顺序ID生成机制,于是自己开发了一套全局唯一ID生成服务:Snowflake。GitHub地址:https://github.com/twitter/snowflake。根据twitter的业务需求,snowflake系统生成64位的ID。由3部分组成:

    41位的时间序列(精确到毫秒,41位的长度可以使用69年)
    10位的机器标识(10位的长度最多支持部署1024个节点)
    12位的计数顺序号(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)
    

    最高位是符号位,始终为0。

    • 优点:高性能,低延迟;独立的应用;按时间有序。
    • 缺点:需要独立的开发和部署。

    :last_insert_id()的值是由MySQL server来维护的,而且是为每条连接维护独立的值,也即,某条连接调用last_insert_id()获取到的值是这条连接最近一次insert操作执行后的自增值,该值不会被其它连接的sql语句所影响。这个行为保证了不同的连接能正确地获取到它最近一次insert sql执行所插入的行的自增值,也就是说,last_insert_id()的值不需要通过加锁或事务机制来保证其在多连接场景下的正确性

  • 相关阅读:
    Objective-C传递数据小技巧
    得到当前活动的controller
    ios7去除手势滑动返回
    生活小常识
    通过email分享
    release下去除nslog宏
    AFNetworking VS ASIHTTPRequest
    web服务器和应用服务器
    mac 搭建git服务器
    UIKit基础:14-序列帧动画的简单介绍
  • 原文地址:https://www.cnblogs.com/qiumingcheng/p/5409491.html
Copyright © 2011-2022 走看看