Como crear hash alfanumérico autoincrementado en php y mysql?

Iniciado por WHK, 17 Octubre 2010, 05:03 AM

0 Miembros y 1 Visitante están viendo este tema.

WHK

Hola, se me ocurrió hacer un sistema web que lleva hashses únicos y deben ser lo más cortos posible, quería poner los primeros 5 carácteres de un md5(microtime()) pero qujiero evitar las colisiones, además se me ocurrió otra manera aún mas cotra de hacer hashses sin tener colisiones.

Este sistema es muy similar a tinyurl por lo tanto hay dos tipos de hashses, uno generado por el sistema y uno personalizado opcional.

La idea que tube es que primero comienze el id del enlace con 0,1,2,3,4,5... despues 7,8,9,a,b,c,d,e... despues mayusculas ...x,y,z,A,B,C... y cuando llegue a Z comenzar otraves.. X,Y,Z,01,02,03,04,05... despues 0X,0Y,0Z,10,11,12,13,14... 1x,1y,1z,1A,1B...
se entiende? xD

De esta forma generaría hashses que contengan números y letras mayusculas y minúsculas abarcando todas las combinaciones posibles y así hacer hashses de uno, dos, tres carácteres sin tener colisiones.

Para esto habia hecho un pseudocódigo donde..
Código (php) [Seleccionar]
function calcula_alias(){
sql: obtiene el aliaz mas corto y el último alfabético con límite 1
verifica desde el ultimo caracter hasta el primero
del 0 al 9 , de la a a la z y de la A a la Z
si es Z revisa el siguiente
si llega al final agregar uno y resetear todos a 0
}


de esta forma lograría hacer el autoincrementado pero el problema es que el usuario puede ingresar su hash personalizado, por lo tanto digamos que alguien ingresa "ZZZ" como de dormir y cuando llegue el hash a tres carácteres se va a seleccionar ese porque será el ultimo de la tabla y me va a joder todas las demás combinaciones entre 000 y ZZZ, ahora, tampoco puedo tomar el primero porque si tomo el aaa quien me dice que no hay un aab.

Se entiende mi rompecabezas? xDD el sistema está muy muy útil ya que solucionaría el problema que ningún hosting de archivos ha podido solucionar, ni si quiera facebook ya que ellos utilizan un hash correspondiente a muchas cosas para evitar colisiones, imageshack, megaupload, tinyurl, etc , a todos les solucionaría la vida con este sistema xD pero aún se me está haciendo un poco complicado.

También pensé que si el hash se repite entonces anteponer un hash aleatorio de 5 carácteres pero no es la idea.

Conversando con nakp, si no me resulta lo que haré es utilizar el id numérico y sacar el max() del id  y verificar si existe en la columna de los hashses , solo que como será un string se me hará un poco complejo la verificación, pero es posible.

¿Alguien tiene alguna idea para que me de una mano?

Mientras tanto me conformé con un hash de 5 carácteres con algunos símbolos para evitar una colisión

Código (php) [Seleccionar]
function calcula_alias($cantidad = 5){
$caracteres = '=-_{}$;,abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
for($cuenta = 0; $cuenta <= $cantidad; $cuenta++){
 $hash .= $caracteres[rand(0,strlen($caracteres) - 1)];
}
return $hash;
}

Og.

Código (php) [Seleccionar]

function calcHash($num)
{
$chars = 'zaq1xsw2cde3vfr4bgt5nhy6mju7ki8lo9p0ZAQXSWCDEVFRBGTNHYMJUKILOP';
$hash = "";
$cont = 0;
do {
$pila[$cont] = $chars[$num%strlen($chars)];
$num = (int)$num/strlen($chars);
$cont++;
} while($num);
$cont--;
while($cont--)
$hash .= $pila[$cont];
return $hash;
}


Esa función te hará las combinaciones basadas en un numero.
Ahora, que tal que guardas el numero del ultimo ID generado en una tabla aparte. Y cada ves que metas un nuevo ID le sumas 1 al anterior y posteriormente revisas en la tabla para ver si ese nuevo ID no ha sido previamente reservado (los ID's que puedes elegir). Después de guardar el nuevo ID actualizas el campo que lleva el ultimo ID aleatorio generado.

Espero te sirva.
|-

WHK

vale, digamos que 5 personas diferentes ingresaron el id 500,501,502 y 503, ahora digamos que vamos en el id 499, al procesarlo vemos si existe el 500, como existe verifica 501 pero este ya existe asi que buelve a verificar... 503, pero también está....
ahora digamos que hay mil números ya ingresados xDD no voy a hacer mil querys verificando una por una si ya existe, además no es necesario saber el último id ingresado en una nueva tabla, para eso usaría last_insert() o max() pero aún así fallaría

gracias de todas formas

Og.

#3
Ok, crees factible una tabla de respaldo?
algo asi:


IDusuado
11
20
30
41
51
60
71
...

Entonces para saber que nuevo ID asignaras haras una consulta asi:
Código (sql) [Seleccionar]
SELECT `ID`  from `tabla` WHERE usado='0' ORDER BY ID LIMIT 1;

Y cada ves que uses un nuevo ID lo tachas de esta tabla marcándolo con un 1.
El problema radica en que para cubrir todas las combinaciones de ID's de 5 caracteres harías una tabla con 916,132,832 campos.
No se si mysql pueda manejar esa cantidad de datos :P
|-