由于要用到固定长度的随机字符串。
首先是一段PHP代码
1 $str_md5=md5(uniqid()); 2 $rand = mt_rand(1, 28); 3 $str1=substr($str_md5,$rand,6); 4 $rand = mt_rand(1, 28); 5 $str2=substr($str_md5,$rand,6); 6 $rand = mt_rand(1, 28); 7 $str3=substr($str_md5,$rand,6); 8 $code=substr($str1.$str2.$str3,0,8);

生成180000个随机字符串,图中是按照重复数量倒序排列,可以看到基本都有重复的。不过也是比较理想的。
由于想提升一下自己的C语言能力,所以用C重新写了一下随机生成字符串。
其中用到了随机数函数srand(),rand();
不过折腾一两个小时,随机数还是有问题。并发访问时时间可能几乎为同时,那么srand给的种子时间可以视为相同的。这样就导致了,产生的随机数也是一样的。从而产生的随机字符串也是一样的。循环输出随机字符串,几乎都是一模一样的。
后来想到了ukey,这个扩展可以实现唯一的ID,那么访问都产生唯一的ID,是不是可以将这个ID作为种子时间。答案是肯定的。

上图是产生的随机字符串,可以自定义长度。也同样可以输出只有数字的字符串。相较PHP所产生的随机字符串重复率更低且速度更快。
1 PHP_FUNCTION(get_random__num_str) 2{ 3 int length=8; 4 5 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE) 6 { 7 length=8; 8 9 } 10 length++; 11 int flag, i; 12 char* string; 13 __uint64_t timestamp = realtime(); 14 __uint64_t retval; 15 int len; 16 char buf[128]; 17 18 if (timestamp == 0ULL) { 19 RETURN_FALSE; 20 } 21 22 spin_lock(lock, pid); 23 24 if (context->last_timestamp == timestamp) { 25 context->sequence = (context->sequence + 1) & context->sequence_mask; 26 if (context->sequence == 0) { 27 timestamp = skip_next_millis(); 28 } 29 30 } else { 31 context->sequence = 0; /* Back to zero */ 32 } 33 34 context->last_timestamp = timestamp; 35 36 retval = ((timestamp - context->twepoch) << context->timestamp_left_shift) 37 | (context->datacenter_id << context->datacenter_id_shift) 38 | (worker_id << context->worker_id_shift) 39 | context->sequence; 40 41 spin_unlock(lock, pid); 42 //printf('%ld',retval); 43 srand((unsigned)retval); 44 //srand((unsigned) time(NULL )); 45 if ((string = (char*) emalloc(length)) == NULL ) 46 { 47 //myLog("Malloc failed!flag:14\n"); 48 RETURN_NULL() ; 49 } 50 51 for (i = 0; i < length - 1; i++) 52 { 53 flag = rand() % 3; 54 55 switch (flag) 56 { 57 case 0: 58 string[i] = '1' + rand() % 5; 59 break; 60 case 1: 61 string[i] = '2' + rand() % 7; 62 break; 63 case 2: 64 string[i] = '0' + rand() % 10; 65 break; 66 default: 67 string[i] = '9'; 68 break; 69 } 70 71 72 73 } 74 string[length - 1] = '\0'; 75 RETURN_STRINGL(string,length,0); 76} 77 PHP_FUNCTION(get_random_str) 78{ 79 int length=8; 80 81 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE) 82 { 83 length=8; 84 85 } 86 length++; 87 int flag, i; 88 char* string; 89 __uint64_t timestamp = realtime(); 90 __uint64_t retval; 91 int len; 92 char buf[128]; 93 94 if (timestamp == 0ULL) { 95 RETURN_FALSE; 96 } 97 98 spin_lock(lock, pid); 99 100 if (context->last_timestamp == timestamp) { 101 context->sequence = (context->sequence + 1) & context->sequence_mask; 102 if (context->sequence == 0) { 103 timestamp = skip_next_millis(); 104 } 105 106 } else { 107 context->sequence = 0; /* Back to zero */ 108 } 109 110 context->last_timestamp = timestamp; 111 112 retval = ((timestamp - context->twepoch) << context->timestamp_left_shift) 113 | (context->datacenter_id << context->datacenter_id_shift) 114 | (worker_id << context->worker_id_shift) 115 | context->sequence; 116 117 spin_unlock(lock, pid); 118 //printf('%ld',retval); 119 srand((unsigned)retval); 120 //srand((unsigned) time(NULL )); 121 if ((string = (char*) emalloc(length)) == NULL ) 122 { 123 //myLog("Malloc failed!flag:14\n"); 124 RETURN_NULL() ; 125 } 126 127 for (i = 0; i < length - 1; i++) 128 { 129 flag = rand() % 3; 130 131 switch (flag) 132 { 133 case 0: 134 string[i] = 'A' + rand() % 26; 135 break; 136 case 1: 137 string[i] = 'a' + rand() % 26; 138 break; 139 case 2: 140 string[i] = '0' + rand() % 10; 141 break; 142 default: 143 string[i] = 'x'; 144 break; 145 } 146 147 148 149 } 150 string[length - 1] = '\0'; 151 RETURN_STRINGL(string,length,0); 152}

上图是PHP生成18W随机字符串所用的时间

上图是C扩展生成18W随机字符串所用的时间
所用的服务器都是1G内存 双核的阿里云服务器。
只要在ukey中加入上如代码就可以生产随机字符串和随机长度数字字符串