この記事では、php乱数とc拡張乱数について紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。
固定長のランダム文字列が使用されるためです。
最初は php コードの一部です。
$str_md5=md5(uniqid()); $rand = mt_rand(1, 28); $str1=substr($str_md5,$rand,6); $rand = mt_rand(1, 28); $str2=substr($str_md5,$rand,6); $rand = mt_rand(1, 28); $str3=substr($str_md5,$rand,6); $code=substr($str1.$str2.$str3,0,8);
180000 個のランダムな文字列を生成します。画像は、基本的に繰り返しがあることがわかります。しかし、それは理想でもあります。
c 言語のスキルを向上させたかったので、ランダムに生成された文字列を c で書き直しました。
乱数関数 srand() と rand() が使用されます。
しかし、1 ~ 2 時間苦労しても、乱数に関する問題がまだ残ります。同時アクセス時はほぼ同時の時刻となる場合があるため、srandで与えられるシード時刻は同一とみなしてよい。これにより、生成される乱数は同じになります。結果として得られるランダムな文字列は同じです。ほぼすべて同じ、ランダムな文字列をループアウトします。
後で、ukey のことを思いつきました。この拡張機能は一意の id を実装できます。そうすると、アクセスするたびに一意の id が生成されます。この id をシード時間として使用できますか?答えは「はい」です。
上の図は生成されたランダムな文字列で、長さはカスタマイズできます。数値のみの文字列を出力することも可能です。 php で生成されるランダム文字列と比較して、繰り返し率が低く、速度が高速です。
PHP_FUNCTION(get_random__num_str) { int length=8; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE) { length=8; } length++; int flag, i; char* string; __uint64_t timestamp = realtime(); __uint64_t retval; int len; char buf[128]; if (timestamp == 0ULL) { RETURN_FALSE; } spin_lock(lock, pid); if (context->last_timestamp == timestamp) { context->sequence = (context->sequence + 1) & context->sequence_mask; if (context->sequence == 0) { timestamp = skip_next_millis(); } } else { context->sequence = 0; /* Back to zero */ } context->last_timestamp = timestamp; retval = ((timestamp - context->twepoch) << context->timestamp_left_shift) | (context->datacenter_id << context->datacenter_id_shift) | (worker_id << context->worker_id_shift) | context->sequence; spin_unlock(lock, pid); //printf('%ld',retval); srand((unsigned)retval); //srand((unsigned) time(NULL )); if ((string = (char*) emalloc(length)) == NULL ) { //myLog("Malloc failed!flag:14\n"); RETURN_NULL() ; } for (i = 0; i < length - 1; i++) { flag = rand() % 3; switch (flag) { case 0: string[i] = '1' + rand() % 5; break; case 1: string[i] = '2' + rand() % 7; break; case 2: string[i] = '0' + rand() % 10; break; default: string[i] = '9'; break; } } string[length - 1] = '\0'; RETURN_STRINGL(string,length,0); } PHP_FUNCTION(get_random_str) { int length=8; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE) { length=8; } length++; int flag, i; char* string; __uint64_t timestamp = realtime(); __uint64_t retval; int len; char buf[128]; if (timestamp == 0ULL) { RETURN_FALSE; } spin_lock(lock, pid); if (context->last_timestamp == timestamp) { context->sequence = (context->sequence + 1) & context->sequence_mask; if (context->sequence == 0) { timestamp = skip_next_millis(); } } else { context->sequence = 0; /* Back to zero */ } context->last_timestamp = timestamp; retval = ((timestamp - context->twepoch) << context->timestamp_left_shift) | (context->datacenter_id << context->datacenter_id_shift) | (worker_id << context->worker_id_shift) | context->sequence; spin_unlock(lock, pid); //printf('%ld',retval); srand((unsigned)retval); //srand((unsigned) time(NULL )); if ((string = (char*) emalloc(length)) == NULL ) { //myLog("Malloc failed!flag:14\n"); RETURN_NULL() ; } for (i = 0; i < length - 1; i++) { flag = rand() % 3; switch (flag) { case 0: string[i] = 'A' + rand() % 26; break; case 1: string[i] = 'a' + rand() % 26; break; case 2: string[i] = '0' + rand() % 10; break; default: string[i] = 'x'; break; } } string[length - 1] = '\0'; RETURN_STRINGL(string,length,0); }
上の図は、php が 18w のランダム文字列を生成するのにかかる時間です。
上の図は18w を生成するための c 拡張機能 ランダムな文字列の生成にかかる時間
使用されるサーバーは、1g メモリとデュアル コアを備えた alibaba cloud サーバーです。
上記のコードを ukey に追加する限り、ランダムな文字列とランダムな長さのデジタル文字列を生成できます。
ukey のアドレス http://www.oschina.net/p/ukey
推奨学習: 「php ビデオ チュートリアル》