一致性哈希的替代算法 shard 可反解vsid php版

 1 /**
 2  * Linux 系统 根据共享内存块获取一个增长的整型
 3  */
 4 function getNxtValFromSharedMemory()
 5 {
 6     $string_seed = 'global_sharedmemory_' . $_SERVER['SERVER_ADDR'] . '_key';
 7 
 8     $sem = $shm = null;
 9     $retry_times = 1;
10     do
11     {
12         //获取一个系统共享内存生成的id resource资源
13         $sem = sem_get($string_seed, 1, 0777);
14         $shm = shm_attach($string_seed, 128, 0777);
15 
16         if (is_resource($sem) && is_resource($shm)) {
17             break;
18         }
19 
20         $cmd = "ipcrm -M 0x00000000; ipcrm -S 0x00000000; ipcrm -M {$string_seed} ; ipcrm -S {$string_seed}";
21         $last_line = exec($cmd, $output, $retval);
22         //var_dump($last_line, $cmd, $output, $retval);
23 
24         if ($retval !== 0)
25         {
26             die('System cannot create sem/shm resource by php');
27         }
28     } while($retry_times-- > 0);
29     if(!sem_acquire($sem))
30     {
31         die('System sem error');
32     }
33 
34     $next_value = false;
35     if (shm_has_var($shm, $string_seed))
36     {
37         $next_value = shm_get_var($shm, $string_seed) + 1;
38         shm_put_var($shm, $string_seed, $next_value);
39     }
40     else
41     {
42         $next_value = 1;
43         shm_put_var($shm, $serial_key, $next_value);
44     }
45 
46     shm_detach($shm);
47     sem_release($sem);
48     return $next_value;
49 
50 }

//求二进制
1 $tr = 5672264790966273; 2 $res_2 = ''; 3 do 4 { 5 6 $res_2 = $tr%2 . $res_2; 7 $tr = $tr/2; 8 9 }while($tr > 1); 10 11 echo $res_2; 12 13 exit;
14 $ntime = microtime(true); 15 echo "1、"; 16 echo $ntime; 17 echo "<hr>"; 18 19 $time_sig = intval($ntime * 1000); 20 echo "2、"; 21 echo $time_sig; 22 echo "<hr>";
//这里需要服务器虚节点id 23 $vsid = 4097; 24 $auto_inc_sig = getNxtValFromSharedMemory(); 25 26 $serial_id = $time_sig << 12 | $vsid; 27 echo "3、"; 28 echo $serial_id; 29 echo "<hr>"; 30 31 $serial_id = $serial_id << 10 | ($auto_inc_sig % 1024); 32 echo "4、"; 33 echo $serial_id; 34 echo "<hr>"; 35 36 $s_r = $serial_id >> 10; 37 echo "5、"; 38 echo $s_r; 39 echo "<hr>"; 40 41 //这行 42 $vsid = $s_r & (0xFFF); 43 echo "6、"; 44 echo $vsid; 45 exit;
 1 /**
 2  * 从新格式全局序列ID反解出虚拟shard编号
 3  */
 4 function extractVSID($serialId)
 5 {
 6     if(!$serialId || !is_numeric($serialId))
 7         return false;
 8     else
 9         $serialId = (int)$serialId;
10 
11     return $serialId >> 10 & (0xFFF);
12 }
 1 /**
 2  * 生成一个序列ID
 3  *
 4  * 格式:(42B microtime) + (12B vsid) + (10B autoinc)
 5  */
 6 function makeSerialId($vsid)
 7 {
 8     $vsid_max = 4095;
 9     $vsid_min = 1;
10     if(!is_numeric($vsid) || $vsid < $vsid_min || $vsid > $vsid_max)
11         return false;
12     else
13         $vsid = (int)$vsid;
14 
15 
16     $auto_inc_sig = getNextValueByShareMemory();
17     if(empty($auto_inc_sig))
18         return false;
19 
20     $ntime = microtime(true);
21     $time_sig = intval($ntime * 1000);
22     $serial_id = $time_sig << 12 | $vsid;
23     $serial_id = $serial_id << 10 | ($auto_inc_sig % 1024);
24     return (string)$serial_id;
25 }

容易出现id冲突,待解决

 1 /**
 2  * 通过本机共享内存件来生成一个auto_increment序列
 3  */
 4 function getNextValueByShareMemory()
 5 {
 6     $addr = '127.0.0.1';
 7     if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
 8         $addr = $_SERVER['HTTP_X_FORWARDED_FOR'];
 9     elseif(!empty($_SERVER['SERVER_ADDR']))
10         $addr = $_SERVER['SERVER_ADDR'];
11 
12     $skey = 'global_serial_generator_seed_'.$addr;
13     $ikey = crc32($skey);
14 
15     $sem = $shm = null;
16     $retry_times = 1;
17     do
18     {
19         $sem = sem_get($ikey, 1, 0777);
20         $shm = shm_attach($ikey, 128, 0777);
21         if(is_resource($sem) && is_resource($shm))
22             break;
23 
24         $cmd = "ipcrm -M 0x00000000; ipcrm -S 0x00000000; ipcrm -M {$ikey} ; ipcrm -S {$ikey}";
25         $last_line = exec($cmd, $output, $retval);
26     }while($retry_times-- > 0);
27 
28     if(!sem_acquire($sem))
29         return false;
30 
31     $next_value = false;
32     if(shm_has_var($shm, $ikey))
33         shm_put_var($shm, $ikey, $next_value=shm_get_var($shm, $ikey)+1);
34     else
35         shm_put_var($shm, $ikey, $next_value=1);
36 
37     $shm && shm_detach($shm);
38     $sem && sem_release($sem);
39     return $next_value;
40 }