如何防止两个用户获得相同的唯一键?

时间:2017-08-15 08:11:27

标签: php algorithm codeigniter

我正在创建一个生成唯一键的系统。它现在有效。但是,我还没有对很多用户进行过测试。用户可以单击按钮然后获取其唯一编号,就像这样简单。

但是,如果他们在同一时间完全按下按钮(即使是以ms为单位),如何防止多个用户获得相同的唯一键?按钮在客户端,所以我必须在后端做一些事情。

这是唯一的关键看起来像:
19/XXXXXX-ABC/XYZ

XXXXXX是从000001999999的自动增量编号。我有这个代码,但不知道它是否足够可靠来处理我的问题。

    $autoinc = $this->MPenomoran->get_surat($f_nomor)->jumlah_no+1; //count data in table and added 1

    $no_1   = date('y')+2;
    $no_2   = str_pad($autoinc, 6, '0', STR_PAD_LEFT);
    $no_3   = "-ABC/XYZ";

    $nomor      = $no_1."/".$no_2.$no_3; 

    $returned_nomor     = $nomor;           

    $success =  array ('nomor' => $returned_nomor); //sent unique keys to user's view

1 个答案:

答案 0 :(得分:2)

您似乎不想出来告诉我们这个平台是什么,或者该平台的限制是什么。

跳出来的第一件事是您的格式受到年份限制,总共999999个唯一键。非常奇怪,但可能你理解这个限制,并且需要输入一些代码来处理达到最大数量。

<强>途径

基于REDIS

使用INCR的REDIS服务器非常简单。既然INCR是原子的,那么你基本上只需要创建一个名为你的年份+ 2的密钥,如果它不存在,并且从那里开始使用INCR就可以得到一个解决方案。

你需要利用一些php redis client,其中有各种各样的优点和缺点,我不打算进入。

Redis也非常适合缓存,所以如果可能的话,这是我要研究的第一件事。

基于MySQL

使用mysql有一些不同的解决方案。他们参与其中,所以我只是概述它们,因为我不想花时间写小说。

注意: Y 您需要将这些转换为相应的PHP代码(mysqli或PDO),如上所述,参数传递,交易开始等

MySQL - 创建自己的序列生成器

  1. 使用以下基本结构创建名为“Sequence”的表:

    name varchar(2) PK nextval unsigned int default 1 发动机= InnoDB的

  2. 基础查询将是这样的:

    BEGIN_TRANS;
    SELECT nextval FROM Sequence WHERE name = '$no_1' FOR UPDATE;
    UPDATE Sequence SET nextval = nextval + 1;
    END_TRANS;
    

    此代码模拟序列化的Oracle样式序列。从并发的角度来看是安全的,因为MySQL会短暂锁定行,然后在完成后递增它。

    MySQL - 多值PK的自动增量

    这有一些警告。

    它通常与复制不兼容。 基础表必须是myisam

    name varchar(2) PK
    lastval unsigned int AUTO_INCREMENT PK
    engine=MyISAM
    

    您的基础查询将是:

    INSERT INTO Sequence (name) VALUES ('$no_1')
    

    这取决于支持多列键的mysql,其中第二列是AUTO_INCREMENT。它的行为使得它就像每个唯一名称的序列一样。

    然后,您将使用相关的api内置方法来获取mysql LAST_INSERT_ID()。例如PDO

    其他替代方案

    您还可以使用信号量,带锁定的文件以及各种其他想法来创建一个序列生成器,该序列生成器可以在单片(一个服务器用于所有内容)环境中很好地工作。 MySQL和Redis将服务于一个集群,因此从这个角度来看,这些是更强大的选择。

    重要的是,无论您做什么,都可以使用负载测试器(如siegeBoom)对其进行测试,以在您的网络级别生成多个请求。