Use unique identifier timestamp in a PHP process?

1

Here's the scenario:

A trading site that handles many transactions per second. It is hosted on high-performance multi-core computers at AWS.

The time() of php function is being used to generate a unique transaction identifier.

I do not know if it has ever happened by chance or if it can happen, but is it possible for 2 or more connected users at the same time to generate 2 or more similar identifiers?

    
asked by anonymous 04.05.2017 / 13:31

2 answers

2

Yes, the chance for conflict is great. Ideally, each transaction should receive a unique incremental identifier, but if this is not possible, I recommend that you use a prefix with the machine id. Better still using a hash.

For example:

<?php

 $id = sha1($serverName.time());

You can still add more information as the Session Id.

    
04.05.2017 / 13:47
0

If you deal with many transactions per second and use time() then you have many collisions per second, of course . The time() returns the date in unixtime, the number of seconds counted since 1970 .

So you use time() to be a unique identifier so you can only process one transaction per second. If in the same second two transactions are processed you will use the same date , see this example . / p>

The microtime() in turn informs the microseconds, which is less worse, but still there is risk, if there is no type of block, two transactions have the same identifier.

If you want a unique identifier, or closer to it, use CSPRNG , this will make it random ( is actually deterministic, but finally ). The probability of two transactions generating the same set of bytes is low, and is even smaller if the set of bytes is larger, for example:

$random_bytes = random_bytes(128);

You can use bin2hex / base64 or unpack (which is preferable) to represent the bytes in some way.

If you want to return numeric values you can use:

implode('', unpack("N*", random_bytes(4)));
// Resultado: 555172730
// Resultado: 1360929444

Try this.

The N indicates that it is an unsigned long (always 32 bit, big endian byte order) , each 32 bit ( 4 Bytes ) represents a numeric sequence.

The unpack supports other representations, such as H that returns in hex , every 4 bits is equivalent to a letter / number (0-9 and AF), does exactly what bin2hex does, for example:

unpack("H*", random_bytes(32))[1];
// Resultado: de2e461f0955d58dc4f6fbd55afafb779e976be781651d80832e91824fd22d35
// Resultado: 2688ffde028dc8893446912d057d388571e21dbcafe0c3185c5ec32d7f047f35

Comparison, simulating executing 4 transactions per second ( one transaction every 250000 microseconds ):

time():
1493901169
1493901169
1493901169
1493901170

random_bytes(4) + unpack(N):
930833536
883463788
1732194618
265243744

random_bytes(32) + unpack(H):
a679d799284b4c2e3483c1f457a6d5cf9a500d8b37ecdbc0f804fc614f167ea3
a461dff841f8e43a4c377e507e04a47d6fbd8980a0f46dbb9bcaf2678ebadeac
68bdd0709e3dc2460dadd3dccf25771d98f6665159186270c2869dcaf0e79942
c82dca8125a82925872261bf5fca8ff026b9d0546a39658d8cbdd3a2c5267d33

Try this here.

    
04.05.2017 / 14:33