专栏首页陌无崖知识分享分布式自增数据库ID

分布式自增数据库ID

作者 | 陌无崖

转载请联系授权

引言

今天在写项目的时候学习了一个用代码编写的自增的数据库ID,其实是一个ID缓冲池。使用了golang中chan类型。

建表

我们希望该ID缓冲池可以为我们其他不同的数据表进行ID的生成,因此需要建一个如下表:

CREATE TABLE `uid` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `business_id` varchar(128) COLLATE utf8mb4_bin NOT NULL COMMENT '业务id',
  `max_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '最大id',
  `step` int(10) unsigned NOT NULL DEFAULT '1000' COMMENT '步长',
  `description` varchar(255) COLLATE utf8mb4_bin NOT NULL COMMENT '描述',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_business_id` (`business_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='分布式自增主键';

-- ----------------------------
-- Records of uid
-- ----------------------------
INSERT INTO `uid` VALUES ('1', 'device_id', '1689', '10', '设备id', '2019-10-15 16:42:05', '2020-02-05 06:57:29');
INSERT INTO `uid` VALUES ('2', 'test', '20', '10', '测试', '2020-02-05 06:59:44', '2020-02-05 07:05:12');

代码思路

定义结构体绑定sql

type Uid struct {
    db         *sql.DB
    businessId string
    ch         chan int64//缓冲池的大小
    min, max   int64
}

新建一个UID

// 新建一个Uid并一直生产ID
func NewUid(db *sql.DB, businessId string, len int) (*Uid, error) {
    lid := Uid{
        db:         db,
        businessId: businessId,
        ch:         make(chan int64, len),
    }
    go lid.produceId()
    return &lid, nil
}

生产ID

  • 首先从数据库中加载获得当前数据的最大值
  • 循环生成自增ID
func (u *Uid) produceId() {
    // 从数据库中获取id
    u.reload()

    for {
        if u.min >= u.max {
            // 从数据库中获取id
            u.reload()
        }
        u.min++
        u.ch <- u.min
    }
}

在上述代码中当ch中达到了最大容量,会发生阻塞。

数据库中获得ID

获得数据库中的ID,如果获取失败,将停顿一秒,继续尝试获取

func (u *Uid) reload() error {
    var err error
    for {
        err = u.getFromDB()
        if err == nil {
            return nil
        }

        // 如果获取失败,等待
        time.Sleep(time.Second)
    }
}

操作数据库

func (u *Uid) getFromDB() error {
    var (
        maxId int64
        step  int64
    )
    tx, err := u.db.Begin()
    if err != nil {
        return err
    }
    defer tx.Rollback()
    //sql语句
    sqlquery := "select max_id,step from uid where business_id = ? FOR UPDATE "
    err = tx.QueryRow(sqlquery, u.businessId).Scan(&maxId, &step)
    if err != nil {
        return err
    }
    // 更新数据库中uid的最大值
    update := "update uid set max_id = ? where business_id = ?"
    _, err = tx.Exec(update, maxId+step, u.businessId)
    if err != nil {
        return err
    }
    err = tx.Commit()
    if err != nil {
        return err
    }
    u.min = maxId
    u.max = maxId + step
    return nil
}

有了这个数据库自增ID的管理,当我们分布式操作数据库时,就可以保证不会发生冲突了

END

本文分享自微信公众号 - golang技术杂文(gh_ebbdb61f463e),作者:无崖子天下无敌

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-02-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 数据库 ID 生成方案:数据库自增

    phone 的存在是为了方便插入数据,当插入数据成功时,就产生了自增 id,而对于插入,这里使用的是 replace,replace 会先查找是否存在 phon...

    happyJared
  • Twitter的分布式自增ID算法snowflake (Java版)

    转载自 https://www.cnblogs.com/relucent/p/4955340.html

    allsmallpig
  • 分布式数据库如何实现主键全局自增?

    前面和大家介绍了 MyCat 中数据库不同的分片规则,从留言中看出大家对分布式数据库中间件还挺感兴趣,因此今天就再来一篇,聊一聊主键全局自增要如何实现。

    江南一点雨
  • 分布式数据库如何实现主键全局自增?

    主键自增这应该算是一个非常常见的需求,在单机数据库中,这个需求一个 auto_increment 就能实现,但是在数据库集群中,这个需求却变复杂了,因为存在多个...

    JAVA葵花宝典
  • [MySQL] 数据库自增ID用完了会怎么样

    1.有主键 如果设置了主键,并且一般会把主键设置成自增。 我们知道,Mysql里int类型是4个字节,如果有符号位的话就是[-2^31,2^31-1],无符号位...

    陶士涵
  • 分布式数据库基础:分布式数据库故障

    处理网络分割故障比处理站点故障和报文故障要困难很多,但其发生频率也比站点故障和报文故障低一些。按照故障处理难度升序排列:

    IT技术分享社区
  • 分布式数据库

    分布数据库定义:分布数据库是由一组数据组成的,这组数据分布在计算机网络的不同计算机上,网络中的每个节点具有独立处理的能力(称为场地自洽),可以执行局部应用。同时...

    ellipse
  • 面试官:数据库自增 ID 用完了会咋样?

    哈喽,好久没更新啦。因为最近在面试。用了两周时间准备,在 3 天之内拿了 5 个 offer,最后选择了广州某互联网行业独角兽 offer,昨天刚入职。这几天刚...

    一个优秀的废人
  • HBase 分布式数据库

    在5、6年前,我们就希望能用分布式存储和分布式数据库来替代集中存储,觉得分布式廉价,而且高可靠。

    birdskyws
  • Twitter的分布式自增ID算法snowflake(雪花算法) - C#版

    概述 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID...

    冰封一夏
  • 面试官:数据库自增ID用完了会怎么样?

    看到这个问题,我想起当初玩魔兽世界的时候,25H难度的脑残吼的血量已经超过了21亿,所以那时候副本的BOSS都设计成了转阶段、回血的模式,因为魔兽的血量是int...

    艾小仙
  • 分布式图数据库 Nebula RC2 发布:增强了 CSV Importer 功能

    本次 RC2 主要新增 GO FROM ... REVERSELY 和 GROUP BY 等语句,Storage Engine 也更灵活,用户可以通过 Cons...

    NebulaGraph
  • 浅谈分布式数据库

    文章集中整理总结mysql分库分表开源产品,分布式数据库的设计,以及实际应用案例等相关内容,部分附上本文作者实际应用过程中的理解。

    庞小明
  • 分布式NewSQL数据库TiDB

    TiDB 是 PingCAP 公司基于 Google Spanner / F1 论文实现的开源分布式 NewSQL 数据库。 https://github.co...

    李海彬
  • 数据库分布式事务

    分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作...

    架构探险之道
  • 分布式数据库 RethinkDB 2.0 发布

    ? RethinkDB在官网宣布,经过五年的发展,RethinkDB 2.0 正式发布,用于实践!RethinkDB团队表示,该项目有着2000多个改进、1...

    小小科
  • django models里数据表插入数据id自增操作

    每次数据插入进去都会更新一次,并且Id都为1,就变成update,而不是insert

    砸漏
  • 分布式数据库CAP原理

    事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性:

    乐心湖
  • 当数据库遇到分布式

    数据库通常有着完善的事务支持,但是局限于单机的存储和性能,于是就出现了各种分布式解决方案。最近读了《Designing Data-Intensive Appli...

    架构师修炼

扫码关注云+社区

领取腾讯云代金券