Recently to do a conversion function generated by the code, before a 32-bit only code generator, but in the business requirements, a 32-bit conversion code a bit too long, the user will have trouble in the application to fill in, is not very friendly, can make a qr code in the form of a sweep line, but there are still in the business for input into the behavior of the code, Therefore, this paper mainly focuses on the exploration of generating exchange codes with the shortest possible characters, while ensuring the uniqueness and reuse of the generation mechanism (that is, different kinds of exchange codes can be generated by using this mechanism)
The following sample code is written based on TPRCMS
Exploration 1: Base conversion
The resulting 32-bit unique code is a hexadecimal hash string. I wondered if I could shorten the string length by increasing the base, so I came up with the following code
ConvertLogic ConvertLogic ConvertLogic ConvertLogic ConvertLogic ConvertLogic ConvertLogic
The sample code
$uuid = "cd5fd2cfeb40aafe060f4d9597348be7";
$str = ConvertLogic::convert( $uuid, 16, 62);
Copy the code
The output
string(32) "cd5fd2cfeb40aafe060f4d9597348be7"
string(22) "6fxdxREtzxq6qNdSghGm7t"
Copy the code
After conversion, it is found that the length is compressed to 21 ~ 22 bits at most, which is still a little long
Exploration 2: Uniqid () to base 62
Uniqid () can generate a hexadecimal unique code of more than 13 bits; converting it to base 62 yields a shorter string
The experimental code
$uuid = uniqid('code'); $resule = ConvertLogic::convert( $uuid, 16, 62); String (17) "5a5C5B182386" // String (12) "7hoyVkRTi"Copy the code
Through multiple generation, the results show the following shortcomings:
1. In a batch of exchange codes generated in this way, only the last few bits are changed. If the generation interval is very close, only the last two bits are different and the first ones are the same, which may result in easy guessing and easy to be tested. 2. Lack of uniqueness. It is difficult to guarantee uniqueness in batch concurrent generation of multiple machines
Discovery 3: Generate a random 12-bit string using Redis to ensure uniqueness
The sample code
//$category_uniq is the hash of the class, RedisService::redis()->switchDB()->hSetNx('code_hash_list_'.$category_uniq, $code, $category_uniq); False is returned if the same exchange code already exists under the same categoryCopy the code
Random character generation code
Random string generator / * * * * @ $@ param length * param string $strPol * @ return null | string * / public static function getRandChar($length = 15,$strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"){ $str = null; $max = strlen($strPol)-1; for($i=0; $i<$length; $i++){ $str.=$strPol[rand(0,$max)]; //rand($min,$Max) generates a random integer between min and Max. }Copy the code
Through random generation of serial 1 million times, it was found that as the data gradually increased, the probability of repetition would gradually increase, which meant that more and more times of regeneration.
Exploration 4: use redis counter to “get tickets”, with transaction operation to ensure the accuracy of the counter, one exchange code to get a ticket
The purpose of the 4-digit ticket number is to ensure uniqueness, and the random code is to prevent the correct value from being easily tested. In this way, even if you know that the first 4 places are ticket numbers, you can add one, but the last 12 places can be difficult to try. Moreover, a 4-digit ticket number can support a category of 14,538,000 exchange codes (base 62, “ZZZZ”-“1000”), even if the ticket number is not enough, the length of the ticket code is +1. Another advantage of this mechanism is that you can modify the exchange code length according to the situation. For example, the current business only needs to generate a few hundred codes, And there are not too many requirements for security, so you can only need “2 bits of ticket code +4 bits of random character”
- Ticket code
private static function ticket($category_uniq , $baseCount){
$key = 'code_ticket_'.$category_uniq;
RedisService::redis()->switchDB()->watch($key);
$count = RedisService::redis()->switchDB()->multi()
->incr($key)
->exec();
if($count === false){
return self::ticket($category_uniq, $baseCount);
}
$ticket = $baseCount + $count;
return $ticket;
}
Copy the code
Conversion code batch generation complete logic code: CodeLogic
Expand the thinking
- Short url
Using the ticket number to 62 base system of thinking, in fact, can also do short url only need 6 bits can meet more than 50 billion url and each time to add a short url, only need to get a ticket code to the back end, and establish the corresponding relationship between the ticket code and the real url (KV) can be