がるの健忘録 このページをアンテナに追加 RSSフィード

2017-03-22

[][]CAS実装……の前提のお話

ふと、色々と紆余曲折があった末として「MagicWeaponのdata_clumpで、cas形式の楽観的ロック、実装してみようかしらん?」というような発想がありまして。

その前提として「cas tokenど〜やって実装しよう?」から、比較的現実的な可能性があるあたりを妄想して、その辺の実装の欠片を思いついたので、おおむね、メモ用途でw


端的には「bigint(8byte) unsigned相当の整数」をランダムで持たせたら、大体、トークン足りえるんじゃないかなぁ? と、妄想をしまして。

8byteなら、index切っても、メモリ空間の圧迫が「そんなもんだろう」程度、だろうし。

渡し方については……MySQLであれば……二種類あるなぁ。


mysql> SELECT CAST(0xffffffffffffffff AS UNSIGNED);

+--------------------------------------+

| CAST(0xffffffffffffffff AS UNSIGNED) |

+--------------------------------------+

| 18446744073709551615 |

+--------------------------------------+

mysql> SELECT CONV('ffffffffffffffff', 16, 10);

+----------------------------------+

| CONV('ffffffffffffffff', 16, 10) |

+----------------------------------+

| 18446744073709551615 |

+----------------------------------+


………ん?

mysql> SELECT CAST('0xffffffffffffffff' AS UNSIGNED);

+----------------------------------------+

| CAST('0xffffffffffffffff' AS UNSIGNED) |

+----------------------------------------+

| 0 |

+----------------------------------------+

あぁ文字列にすると駄目なのか。

って事は、CONV関数だな。こっちなら「文字列」として渡せる。

まぁ、MySQLに方法があるんだ、ほかのRDBでもあるだろうw(ざつ)


んで。

だとするとあとは「8byte整数相当の値をランダムにとってくる」と、なんとなく行けるっぽくて。

後は「重複しねぇよなぁ」を、雑にテストしてみるとよいんじゃなかろうか、って思う。


Linux的に手っ取り早いのは /dev/urandom デバイスでしょ、ってんで、確認かねて、以下のコードを動かしてみた。

<?php

$data = [];
for($i = 0; $i < 100000; ++$i) {
    $h = bin2hex(file_get_contents('/dev/urandom', false, NULL, 0, 8));
    if (false === isset($data[$h])) {
        $data[$h] = 1;
    } else {
        echo "ng... \n";
    }
}

重複が発生したら教えてくれる、的な子。

とりあえず10万回。

……ま〜ま〜時間かかるのな。ほんのわずかにびっくりしたおw


何度か動かしてみましたが、(おおよそ予想通り)一度もぶつからなかったので。

多分、いけるんじゃないかなぁ、的な。


どこかで、気が向いたり体力が向いたりしたら、CASを実際に実装してみませう。

って事で、とりあえず「実装するために一番重要な部分」を、軽くテストしてみました。


突っ込みなどあったら歓迎いたしますので、是非。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/gallu/20170322/p1