<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>中文 &#187; lgg201</title>
	<atom:link href="http://software.intel.com/zh-cn/blogs/author/lgg201/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/zh-cn/blogs</link>
	<description></description>
	<lastBuildDate>Sat, 26 May 2012 06:34:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>PHP利用共享内存构建计数器完成自增数值id生成 -- 适用于网页游戏携带区服号的数值id生成</title>
		<link>http://software.intel.com/zh-cn/blogs/2010/12/16/phpid-id/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2010/12/16/phpid-id/#comments</comments>
		<pubDate>Thu, 16 Dec 2010 11:04:00 +0000</pubDate>
		<dc:creator>lgg201</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[并行计算]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2010/12/16/phpid-id/</guid>
		<description><![CDATA[我们之前的id生成是直接用的php的uniqid 存在的问题有： 1. 高并发下容易重复：当高并发适用uniqid来产生唯一id的时候，我的测试数据是：1000并发，每并发产生1000次，实际输出63万uid（可能是标准输出原因未全部输出），5次重复 2. mysql中使用字符串类型的key存在性能问题 使用这里创建的ud_uniqid带来的改变： 优点1. 高并发重复几率降低：我的测试数据是：1000并发，每并发产生1000次，实际输出93万，无重复 优点2. 使用过程中，可以产生唯一的递增数值id，作为mysql主键有性能优势 缺点1. 性能比uniqid略低，耗时约为uniqid的1.5倍（不过在10e-5 -- 10e-4级别的时间差，1.5倍应该可以忽略） 缺点2. windows不能使用（windows不支持usleep） 缺点3. 由于使用了共享内存，所以需要在服务器开启的时候读取上一次的最大值，服务器关闭的时候写入当前的最大值 下面直接上代码了， 代码里面注释很清楚的： view plaincopy to clipboardprint? &#60;?php /** * functions: 产生64位唯一自增随机数，用于游戏唯一数值id生成 * 1. 数值分布：9位区号 3位服号 32位id号 10位随机码 10位随机码 * 2. 可提供范围：512区，每区8个游戏服务器，提供42亿id * 3. 重复性测试：100并发，每个并发进程产生1000次随机数，无重复 * 4. 性能测试：与系统自带uniqid函数相比，耗时为其1.5倍 * author: selfimpr * blog: http://blog.csdn.net/lgg201 * mail: lgg860911@yahoo.com.cn [...]]]></description>
			<content:encoded><![CDATA[<p>我们之前的id生成是直接用的php的uniqid<br />
存在的问题有：<br />
1. 高并发下容易重复：当高并发适用uniqid来产生唯一id的时候，我的测试数据是：1000并发，每并发产生1000次，实际输出63万uid（可能是标准输出原因未全部输出），5次重复<br />
2. mysql中使用字符串类型的key存在性能问题<br />
使用这里创建的ud_uniqid带来的改变：<br />
优点1. 高并发重复几率降低：我的测试数据是：1000并发，每并发产生1000次，实际输出93万，无重复<br />
优点2. 使用过程中，可以产生唯一的递增数值id，作为mysql主键有性能优势<br />
缺点1. 性能比uniqid略低，耗时约为uniqid的1.5倍（不过在10e-5 -- 10e-4级别的时间差，1.5倍应该可以忽略）<br />
缺点2. windows不能使用（windows不支持usleep）<br />
缺点3. 由于使用了共享内存，所以需要在服务器开启的时候读取上一次的最大值，服务器关闭的时候写入当前的最大值<br />
下面直接上代码了， 代码里面注释很清楚的：<br />
view plaincopy to clipboardprint?<br />
&lt;?php<br />
/**<br />
* functions: 产生64位唯一自增随机数，用于游戏唯一数值id生成<br />
* 1. 数值分布：9位区号 3位服号 32位id号 10位随机码 10位随机码<br />
* 2. 可提供范围：512区，每区8个游戏服务器，提供42亿id<br />
* 3. 重复性测试：100并发，每个并发进程产生1000次随机数，无重复<br />
* 4. 性能测试：与系统自带uniqid函数相比，耗时为其1.5倍<br />
* author: selfimpr<br />
* blog: http://blog.csdn.net/lgg201<br />
* mail: lgg860911@yahoo.com.cn<br />
*/<br />
/**<br />
* 产生子进程<br />
* $func_name: 子进程处理的过程函数<br />
* 可接不定参数，为子进程过程函数需要的参数<br />
*/<br />
function new_child($func_name) {<br />
$args = func_get_args();<br />
unset($args[0]);<br />
$pid = pcntl_fork();<br />
if($pid == 0) {<br />
function_exists($func_name) and exit(call_user_func_array($func_name, $args)) or exit(-1);<br />
} else if($pid == -1) {<br />
echo "Couldn’t create child process.";<br />
} else {<br />
return $pid;<br />
}<br />
}<br />
/**<br />
* 计数生成器<br />
* 采用共享内存生成<br />
* $key: 每个独立的$key标记为一个计数器<br />
* $length: 分配内存大小<br />
*/<br />
function counter($key = 0x1, $length = 256) {<br />
$segment_id = shmop_open($key, 'c', 0777, $length);<br />
$now = intval(shmop_read($segment_id, 0, shmop_size($segment_id))) + 1;<br />
shmop_write($segment_id, (string)$now, 0);<br />
shmop_close($segment_id);<br />
return $now;<br />
}<br />
/**<br />
* 自定义唯一id生成器<br />
* $group_id: 区号<br />
* $server_id: 服号<br />
*/<br />
function ud_uniqid($group_id = 1, $server_id = 1) {<br />
$rand_key1 = rand(0, 1023);<br />
usleep(rand(0, 16));<br />
$rand_key2 = rand(0, 1023);<br />
$id = counter();<br />
return ($group_id &lt;&lt; 55) | ($server_id &lt;&lt; 52) | ($id &lt;&lt; 20) | ($rand_key1 &lt;=0) {<br />
if($f[$l] == $f[$l + 1]) echo $f[$l + 1]."\n";<br />
$l --;<br />
}<br />
}<br />
/**<br />
* 生成uid并输出到标准输出<br />
* $times: 产生次数<br />
*/<br />
function check_repeat_out($times) {<br />
while($i ++ &lt; $times) {<br />
echo ud_uniqid()."\n";<br />
}<br />
}<br />
/**<br />
* 测试重复性(并发生成uid并输出到标准输出)<br />
* $concurrent: 并发数<br />
* $times: 每个并发中产生uid次数<br />
*/<br />
function test_repeat($concurrent, $times) {<br />
while($i ++ &lt; $concurrent) {<br />
new_child(check_repeat_out, $times);<br />
}<br />
}<br />
/**<br />
* 与系统自带uniqid性能对比测试<br />
* $times: 运行多少次进行时间比对<br />
*/<br />
function test_performence($times) {<br />
$time = 0;<br />
while($i ++ &lt; $times) {<br />
$start = microtime(true);<br />
ud_uniqid();<br />
$end = microtime(true);<br />
$time += $end - $start;<br />
}<br />
echo "ud_uniqid($times): $time.\n";<br />
$time = 0;<br />
$i = 0;<br />
while($i ++ repeat.check.dat<br />
* 3. 关闭test_repeat();方法（注释）<br />
* 4. 打开check_repeat('repeat.check.dat'); （测试时请注意文件路径），运行：php ud_uniqid.php，如果不产生输出，则标明无重复<br />
* 性能测试：<br />
* 打开test_performence(); CLI模式运行即可<br />
*/<br />
//test_performence(10000);<br />
//test_repeat(100, 1000);<br />
//check_repeat('repeat.check.dat');<br />
?&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2010/12/16/phpid-id/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

