AUTO_INCREMENT PHP kullanarak kısa benzersiz kimliği nesil?

8 Cevap php

Ben çarpışmaları denetlemek zorunda kalmadan, kısa, benzersiz bir kimlik oluşturmak istiyorum.

Şu anda böyle bir şey yapmak, ama ben şu anda üretmek kimlik rastgele ve bir döngü içinde çarpışma için kontrol can sıkıcı olduğunu ve kayıtların sayısı önemli ölçüde büyürse pahalı olacaktır.

Normalde çarpışmalar endişesi bir sorun değil, ama ben oluşturmak istiyorum benzersiz kimlik tinyurl yaptığı gibi kısa bir benzersiz bir dize 5-8 karakterler, alfa-sayısal, olduğunu.

EDIT: Ben 5 karakter ile başlamak istiyorum ve ben 60 milyon girişleri çarptı, sonra vb vb .. 6 gitmek istiyorum ve.

Bu amaçla, ben kullanıcılardan gizli bir auto_increment değerini kullanabiliyor ve bir MD5 ya da benzersiz bir dize oluşturmak için diğer bazı yöntemi ile yerine onlara sunmak düşünüyordum.

Oluşturulan dizeleri doğrusal olarak görünür, bu yüzden sadece içine auto_incremented kimliği dönüştürme olmamalıdır base 36 [0-9A-Z] biraz çok basit, ama bununla nereye gidiyorum böyle bir işlev şeydir .

EDIT: Security is not an issue as this will not be used to secure information. It is simply a shortcut to a longer string. Thank you.

Önerilerinizi ve gecikme için özür için teşekkür ederiz. Diş Hekimi ..

8 Cevap

You'll need something that's correct by construction, i.e. a permutation function: this is a function that does a one-to-one, reversible mapping of one integer (your sequential counter) to another. Some examples (any combination of these should also work):

  • (PHP fi bir XOR kullanarak, ^) bit bazı inverting
  • bitlerin yerleri takas (($ i & 0xc) >> 2 | ($ i & 0x3) << 2), ya da sadece tüm bitlerin sırasını tersine
  • maksimum aralığı modulo sabit bir değer ekleyerek (yukarıda olanlar ile bu birleştirerek eğer, ikisinin bir faktör olmalıdır)

Örnek: Bu fonksiyon 15'e kadar olan sayılar için 0, 1, 2, 3, 5, .., 13, 4, 12, 7, 15, .. haline dönüştürür:

$i=($input+97) & 0xf;
$result=((($i&0x1) << 3) + (($i&0xe) >> 1)) ^ 0x5;

EDIT

Daha kolay bir şekilde aşağıdaki yapıya sahip bir formül tarafından tanımlanan bir doğrusal congruential jeneratör (genellikle rastgele sayılar için kullanılan LCG), kullanımı olur:

X_n+1 = (a * X_n + c) mod m

good values a, c ve m, X_0 sekansı, x_1 For .. X_m-1 0 ve m-1 ve sadece bir kere arasında tüm numaraları içerir. Şimdi bir doğrusal artan dizinden başlamak ve "gizli" tuşu olarak LCG sırayla next değerini kullanabilirsiniz.

EDIT2

Implementation: You can design your own LCG parameters, but if you get it wrong it won't cover the full range (and thus have duplicates) so I'll use a published and tried set of parameters here from this paper:

a = 16807, c = 0, m = 2147483647

Bu size 2 ** 31 bir dizi verir. Paketi ile () Bir dize, base64_encode () (yukarı 6 önemli karakter, byte başına 6 bit) okunabilir bir dize yapar böylece bu işlevi olabilir gibi çıkan tamsayı alabilirsiniz:

substr(base64_encode(pack("l", (16807 * $index) % 2147483647)), 0, 6)

Muhtemelen mevcut datetime / rasgele sayı bir MD5 hash oluşturmak ve ihtiyacınız uzunluğu (5-8 karakter) onu kesecek ve id alanı olarak depolayabilir.

Bir veritabanında bu bilgileri saklamak kullanıyorsanız, size çarpışma denetimi yapmak için bir for döngüsü kullanmak gerekmez, ama sadece bir deyim yapabileceği - gibi bir şey

SELECT count(1) c FROM Table WHERE id = :id

burada: id yeni oluşturulan kimliği olacaktır. C 0'dan büyükse o zaman zaten var biliyorum.

EDIT

Bu konuda gitmek için en iyi yol olmayabilir. Ama ben bunu bir deneyeyim, bu yüzden ne gerek eşsiz bir kısa dizeye bir numaraları dönüştürme someway ve bu sırayla değil sanırım.

Eğer base64 kodlama zaten kısa bir dize dönüştürme sayısı yok, dediğim gibi sanırım. Eğer bazı "rastgele" değer (benzersiz haritalama) için otomatik oluşturulan id yıllardan arasında bazı eşleme olabilir sırası sorunu önlemek için. Sonra base64 bu eşsiz değerini kodlamak.

Bunu aşağıdaki şekilde haritalama yaratacaktır. 10000000 - 1 geçici bir tablo mağaza değerlere sahiptir. Sıralama rasgele o ve masa haritada içine saklayın.

INSERT INTO MappingTable (mappedId) SELECT values FROM TemporaryTable ORDER BY RAND()

MappingTable 2 alanları id (auto-id oluşturulan bu karşı olmazdı) ve mappedId (sizin için base64 kodlaması oluşturmak ne olduğu) olurdu nerede.

Eğer 10,000,000 yakın olsun tekrar yukarıdaki kodu yeniden çalıştırın ve 10,000,001-20,000,000 ya da buna benzer bir şey ile geçici tablo değerleri değişebilir.

Eğer bit bazı karıştırması için bir bit XOR kullanabilirsiniz:

select thefield ^ 377 from thetable;

+-----+---------+
| a   | a ^ 377 |
+-----+---------+
| 154 |     483 |
| 152 |     481 |
|  69 |     316 |
|  35 |     346 |
|  72 |     305 |
| 139 |     498 |
|  96 |     281 |
|  31 |     358 |
|  11 |     370 |
| 127 |     262 |
+-----+---------+

Yalnızca bir kimlik kaçırmak için kısa benzersiz bir dize arkasındaki şifreleme yöntemini bulmalıyız olarak ben, bu gerçekten güvenli olmayacak düşünüyorum. Lütfen bir ortamda gerçekten sorunlu bir döngü içinde çarpışmalar kontrol ediyor?

An MD5 of an incrementing number should be fine, but I worry that if you're truncating your MD5 (which is normally 128 bits) down to 5-8 characters, you will almost certainly be damaging it's capability to act as a unique signature...

Tamamen doğru. Eğer bir kesik MD5, kendisi tarafından benzersizliği garanti yani değersiz herhangi bir rasgele sayı kadar iyi olacak% 80 çarpışma şansı ulaşmak, özellikle eğer.

Eğer zaten bir veritabanı kullanarak konum beri Ama, neden sadece bir UNIQUE INDEX kullanmak değil mi? Bu şekilde uniquness onay MySQL kendisi (bir döngü kullanarak çok daha verimli bir şekilde) yapılır. Sadece MD5 oluşturulan anahtar ile INSERT yapmaya çalışın, ve başarısız olursa, tekrar deneyin ...

Eğer bir otomatik artış alanını kullanmak ve kullanmak, bir absolutely benzersiz bir değer istiyorum yoksa UUID. Eğer (otomatik artış dışında) başka bir şey kullanmaya karar verirseniz, size çarpışmaları denetlemek değil saçma olurdu.

Artan bir sayıda bir MD5 ince olmalıdır, ama 5-8 karakter aşağı (normalde 128 bit) ve MD5 kesiliyor eğer, neredeyse kesinlikle benzersiz bir imza olarak hareket etmek yetenek zarar olacağını endişe. ..