<?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>Water is.....</title>
	<atom:link href="http://latteye.com/feed" rel="self" type="application/rss+xml" />
	<link>http://latteye.com</link>
	<description>latte</description>
	<lastBuildDate>Thu, 23 Feb 2012 05:04:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>在 Mac OS、Linux 下使用 KeePassX 自动填写表单</title>
		<link>http://latteye.com/2011/12/%e5%9c%a8-mac-os%e3%80%81linux-%e4%b8%8b%e4%bd%bf%e7%94%a8-keepassx-%e8%87%aa%e5%8a%a8%e5%a1%ab%e5%86%99%e8%a1%a8%e5%8d%95.html</link>
		<comments>http://latteye.com/2011/12/%e5%9c%a8-mac-os%e3%80%81linux-%e4%b8%8b%e4%bd%bf%e7%94%a8-keepassx-%e8%87%aa%e5%8a%a8%e5%a1%ab%e5%86%99%e8%a1%a8%e5%8d%95.html#comments</comments>
		<pubDate>Mon, 26 Dec 2011 14:17:00 +0000</pubDate>
		<dc:creator>latteye</dc:creator>
				<category><![CDATA[Life ㄆ 自己生活]]></category>
		<category><![CDATA[keepass]]></category>
		<category><![CDATA[keepassx]]></category>
		<category><![CDATA[lastpass]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[yubikey]]></category>

		<guid isPermaLink="false">http://latteye.com/?p=1458</guid>
		<description><![CDATA[最近几天众多网站数据库都被爆出，现在这里鄙视一下这些网站的技术负责人！你们是猪啊，密码做单向加密是常识中的常识！多调用一个函数会死啊！ 现在我已经不相信国内绝大多数的网站，尽管已经修改过一批密码，但还是不放心。最安全的方式则是使用无规则密码，且各个网站都不同。但是这样无疑在使用上麻烦了许多。 以前我用 KeePass 或者 KeePassX 的时候都是复制粘贴密码，而大多数浏览网页的时候也不需要使用 KeePass，通过网站类型的不同，自己设定几个不同等级的密码即可&#8211;这个方式现在看来已经不够安全了。 Google 个2个小时，发现了 KeePassX 在 MacOS 下自动填写表单功能，记录流水帐一片。 配置方式 首先下载 KeePassX 的 SVN 版本，此包的作者已经将代码提交到了 KeePassX 官方库中，只不过暂时官方未出新版本，所以就用他自己编译的版本吧。 Linux 用户可以看看有没有人编译最新的 SVN 版本，效果应该是一样的。 首先打开 KeePass，创建你自己的密码库文件。 接着设定填写密码快捷键，偏好设置-高级-通用的自动填写快捷键： 这里我把快捷键设置为 Ctrl+Shift+N 。保存退出。 然后添加信息条目。假设我要登陆 人人网（是的，这也是个2B网站，股票从70亿跌倒20亿，至今也没有靠谱的盈利模式，密码也是明文的），在 Firefox 中打开人人网： 现在我们在 KeePassX 里面添加一条记录，填写你的用户名、密码。你完全可以让 KeePassX 自己生成复杂无序的密码，因为从此以后你再也不用记忆密码了。点击 Tool-Auto Type Select Window： 选择你想匹配的窗口： 确定之后备注栏会产生如下代码，这是用来匹配窗口的： 接着点击 Customize Sequence 备注栏加入匹配顺序代码，这里你完全可以自己编辑代码内容，比如有的地方只需要匹配用户名，某些地方需要更多信息等等： 点击 OK 保存此条目。 到这里就可以工作了，打开Firefox，将光标移到人人网站填写用户名处，按下快捷键，网页填写完密码后开始自动登陆！ [...]
Related posts:<ol>
<li><a href='http://latteye.com/2007/12/macmenu-in-arch-gnome.html' rel='bookmark' title='在 Arch Linux Gnome 下使用 Mac Menu'>在 Arch Linux Gnome 下使用 Mac Menu</a></li>
<li><a href='http://latteye.com/2011/12/mac-timemachine-server-base-on-arch-linux.html' rel='bookmark' title='Linux 上搭建 Mac TimeMachine Server'>Linux 上搭建 Mac TimeMachine Server</a></li>
<li><a href='http://latteye.com/2007/12/shntools-mac-cuetools-arch.html' rel='bookmark' title='shntools、mac、cuetools for archlinux'>shntools、mac、cuetools for archlinux</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>最近几天众多网站数据库都被爆出，现在这里鄙视一下这些网站的技术负责人！你们是猪啊，密码做单向加密是常识中的常识！多调用一个函数会死啊！<br />
现在我已经不相信国内绝大多数的网站，尽管已经修改过一批密码，但还是不放心。最安全的方式则是使用无规则密码，且各个网站都不同。但是这样无疑在使用上麻烦了许多。<br />
以前我用 KeePass 或者 KeePassX 的时候都是复制粘贴密码，而大多数浏览网页的时候也不需要使用 KeePass，通过网站类型的不同，自己设定几个不同等级的密码即可&#8211;这个方式现在看来已经不够安全了。<br />
Google 个2个小时，发现了 KeePassX 在 MacOS 下自动填写表单功能，记录流水帐一片。<span id="more-1458"></span></p>
<p><font size=3><strong>配置方式</strong></font></p>
<p>首先下载 <a href="http://www.keepassx.org/forum/viewtopic.php?f=5&#038;t=1920" title="KeePassX MacOS Auto Type" target="_blank">KeePassX 的 SVN 版本</a>，此包的作者已经将代码提交到了 KeePassX 官方库中，只不过暂时官方未出新版本，所以就用他自己编译的版本吧。</p>
<p>Linux 用户可以看看有没有人编译最新的 SVN 版本，效果应该是一样的。</p>
<p>首先打开 KeePass，创建你自己的密码库文件。</p>
<p>接着设定填写密码快捷键，偏好设置-高级-通用的自动填写快捷键：</p>
<p><img src="http://pic.yupoo.com/latteye/BCzFV8iu/medish.jpg" alt="快捷键" /></p>
<p>这里我把快捷键设置为 Ctrl+Shift+N 。保存退出。</p>
<p>然后添加信息条目。假设我要登陆 人人网（是的，这也是个2B网站，股票从70亿跌倒20亿，至今也没有靠谱的盈利模式，密码也是明文的），在 Firefox 中打开人人网：</p>
<p><a href="http://pic.yupoo.com/latteye/BCzyp1II/medish.jpg" title="人人网站标题" target="_blank"></a></p>
<p>现在我们在 KeePassX 里面添加一条记录，填写你的用户名、密码。你完全可以让 KeePassX 自己生成复杂无序的密码，因为从此以后你再也不用记忆密码了。点击 Tool-Auto Type Select Window：</p>
<p><img src="http://pic.yupoo.com/latteye/BCzA3QYu/medish.jpg" alt="选择窗口标题" /></p>
<p>选择你想匹配的窗口：</p>
<p><img src="http://pic.yupoo.com/latteye/BCzEfhE1/medish.jpg" alt="选择窗口" /></p>
<p>确定之后备注栏会产生如下代码，这是用来匹配窗口的：</p>
<p><img src="http://pic.yupoo.com/latteye/BCzEfD7k/medish.jpg" alt="窗口匹配代码" /></p>
<p>接着点击 Customize Sequence</p>
<p><img src="http://pic.yupoo.com/latteye/BCzEfTyI/medish.jpg" alt="产生匹配规则" /></p>
<p>备注栏加入匹配顺序代码，这里你完全可以自己编辑代码内容，比如有的地方只需要匹配用户名，某些地方需要更多信息等等：</p>
<p><img src="http://pic.yupoo.com/latteye/BCzEfMI7/medish.jpg" alt="最终的备注" /></p>
<p>点击 OK 保存此条目。</p>
<p>到这里就可以工作了，打开Firefox，将光标移到人人网站填写用户名处，按下快捷键，网页填写完密码后开始自动登陆！</p>
<p><font size=3><strong>同行比较</strong></font></p>
<p>看到有人讨论 lastpass 和 yubikey 的方案，各人感觉还是 KeePass 让人更安心一点。</p>
<p>1. lastpass 可靠么？还是放在自己硬盘上比较好。<br />
2. yubikey 带了个 USB 设备，同样的，你可以自己生成一个 key 放在 U 盘上，KeePass 永远从 U 盘读取 key 文件。没有 U 盘就打不开主库。我觉得效果是一样的。唯一的不同的 yubikey 还会带来每次按一次的快感，呵呵。<br />
3. 速度！我相信当你配置了合适的快捷键之后，调用 KeePass 的速度远快于伸到 USB 边上摸一下的速度。</p>
<p>&#8212;&#8211;<br />
Update</p>
<p>已知缺陷：<br />
1.淘宝不支持，不过支付宝是支持的<br />
2.像 VeryCD 这样标题栏一直在变换的，比较麻烦。不过 VC 也有专门的登陆页面，那个没问题。</p>
<p>Related posts:</p><ol>
<li><a href='http://latteye.com/2007/12/macmenu-in-arch-gnome.html' rel='bookmark' title='在 Arch Linux Gnome 下使用 Mac Menu'>在 Arch Linux Gnome 下使用 Mac Menu</a></li>
<li><a href='http://latteye.com/2011/12/mac-timemachine-server-base-on-arch-linux.html' rel='bookmark' title='Linux 上搭建 Mac TimeMachine Server'>Linux 上搭建 Mac TimeMachine Server</a></li>
<li><a href='http://latteye.com/2007/12/shntools-mac-cuetools-arch.html' rel='bookmark' title='shntools、mac、cuetools for archlinux'>shntools、mac、cuetools for archlinux</a></li>
</ol>]]></content:encoded>
			<wfw:commentRss>http://latteye.com/2011/12/%e5%9c%a8-mac-os%e3%80%81linux-%e4%b8%8b%e4%bd%bf%e7%94%a8-keepassx-%e8%87%aa%e5%8a%a8%e5%a1%ab%e5%86%99%e8%a1%a8%e5%8d%95.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon EC2 Disk Performence</title>
		<link>http://latteye.com/2011/12/amazon-ec2-disk-performence.html</link>
		<comments>http://latteye.com/2011/12/amazon-ec2-disk-performence.html#comments</comments>
		<pubDate>Wed, 14 Dec 2011 05:22:31 +0000</pubDate>
		<dc:creator>latteye</dc:creator>
				<category><![CDATA[Work / 努力工作]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[sysbench]]></category>

		<guid isPermaLink="false">http://latteye.com/?p=1401</guid>
		<description><![CDATA[本文的目的是为了测试 Amazon EC2 的磁盘性能，从而为数据库搭建做性能估算。使用的测试工具为 sysbench ，这款软件已经很久没更新了。所以全当得出数据为“比较值”。 Amazon 的 Elastic Storage 为 EC2 Instance 提供了软 Raid 的可能性，但是，其 Raid 除了具有数据保障性外，是否有性能提升？提升多少？这是这次实验的目的。 参考别处资料写了一个 sysbench 测试脚本： #!/bin/bash &#160; set -u set -x set -e for size in 2G 4G 8G;do for mode in seqwr seqrd seqrewr rndrd rndwr rndrw;do for blksize in 16384 ; do sysbench --test=fileio --file-num=32 --file-total-size=$size prepare [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>本文的目的是为了测试 Amazon EC2 的磁盘性能，从而为数据库搭建做性能估算。使用的测试工具为 <a href="http://sysbench.sourceforge.net/">sysbench</a> ，这款软件已经很久没更新了。所以全当得出数据为“比较值”。<br />
Amazon 的 Elastic Storage 为 EC2 Instance 提供了软 Raid 的可能性，但是，其 Raid 除了具有数据保障性外，是否有性能提升？提升多少？这是这次实验的目的。<br />
<span id="more-1401"></span></p>
<p>参考别处资料写了一个 sysbench 测试脚本：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">-u</span>
<span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">-x</span>
<span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">-e</span>
<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #c20cb9; font-weight: bold;">size</span> <span style="color: #000000; font-weight: bold;">in</span> 2G 4G 8G;<span style="color: #000000; font-weight: bold;">do</span>
<span style="color: #000000; font-weight: bold;">for</span> mode <span style="color: #000000; font-weight: bold;">in</span> seqwr seqrd seqrewr rndrd rndwr rndrw;<span style="color: #000000; font-weight: bold;">do</span>
<span style="color: #000000; font-weight: bold;">for</span> blksize <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000;">16384</span> ; <span style="color: #000000; font-weight: bold;">do</span>
sysbench <span style="color: #660033;">--test</span>=fileio <span style="color: #660033;">--file-num</span>=<span style="color: #000000;">32</span> <span style="color: #660033;">--file-total-size</span>=<span style="color: #007800;">$size</span> prepare
<span style="color: #000000; font-weight: bold;">for</span> threads <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000;">1</span> <span style="color: #000000;">4</span> <span style="color: #000000;">8</span> <span style="color: #000000;">16</span> <span style="color: #000000;">32</span>; <span style="color: #000000; font-weight: bold;">do</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;===== testing <span style="color: #007800;">$blksize</span> in $ <span style="color: #007800;">$threads</span> threads&quot;</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> PARAMS <span style="color: #007800;">$size</span> <span style="color: #007800;">$mode</span> <span style="color: #007800;">$threads</span> <span style="color: #007800;">$blksize</span> <span style="color: #000000; font-weight: bold;">&gt;</span> sysbench-size-<span style="color: #007800;">$size</span>-mode-<span style="color: #007800;">$mode</span>-threads-<span style="color: #007800;">$threads</span>-blksz-<span style="color: #007800;">$blksize</span>
<span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000;">1</span> <span style="color: #000000;">2</span> <span style="color: #000000;">3</span> ; <span style="color: #000000; font-weight: bold;">do</span>
sysbench <span style="color: #660033;">--test</span>=fileio <span style="color: #660033;">--file-total-size</span>=<span style="color: #007800;">$size</span> <span style="color: #660033;">--file-test-mode</span>=<span style="color: #007800;">$mode</span> <span style="color: #660033;">--max-time</span>=<span style="color: #000000;">180</span> <span style="color: #660033;">--max-requests</span>=<span style="color: #000000;">100000000</span> <span style="color: #660033;">--num-threads</span>=<span style="color: #007800;">$threads</span> <span style="color: #660033;">--init-rng</span>=on <span style="color: #660033;">--file-num</span>=<span style="color: #000000;">32</span> <span style="color: #660033;">--file-extra-flags</span>=direct <span style="color: #660033;">--file-fsync-freq</span>=<span style="color: #000000;">0</span> <span style="color: #660033;">--file-block-size</span>=<span style="color: #007800;">$blksize</span> run <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">tee</span> <span style="color: #660033;">-a</span> sysbench-size-<span style="color: #007800;">$size</span>-mode-<span style="color: #007800;">$mode</span>-threads-<span style="color: #007800;">$threads</span>-blksz-<span style="color: #007800;">$blksize</span> <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">done</span>
<span style="color: #000000; font-weight: bold;">done</span>
sysbench <span style="color: #660033;">--test</span>=fileio <span style="color: #660033;">--file-total-size</span>=<span style="color: #007800;">$size</span> cleanup
<span style="color: #000000; font-weight: bold;">done</span>
<span style="color: #000000; font-weight: bold;">done</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></div></div>

<p><font size=3><strong>基础数值</strong></font></p>
<p>首先，来一款手头上的普通三星 160G 硬盘，将其作为一个参考数值。</p>
<p><strong><font color="Teal">Form 1 &#8212; </font>fsync at end of test</strong></p>
<table border="1">
<tr>
<td>Req&#038;Trans/s</td>
<th>SeqWR</th>
<th>SeqRD</th>
<th>SeqReWr</th>
<th>RndRD</th>
<th>RndWR</th>
<th>RndReWr</th>
</tr>
<tr>
<th>Trd 1</th>
<td>3481\54M</td>
<td>3771\58M</td>
<td>4152\64M</td>
<td>114\1.7M</td>
<td>181\2.8M</td>
<td>123\1.9M</td>
</tr>
<tr>
<th>Trd 4</th>
<td>1951\30M</td>
<td>4403\68M</td>
<td>2324\36M</td>
<td>114\1.7M</td>
<td>181\2.8M</td>
<td>124\1.9M</td>
</tr>
<tr>
<th>Trd 8</th>
<td>1289\20M</td>
<td>4287\66M</td>
<td>2630\41M</td>
<td>114\1.7M</td>
<td>181\2.8M</td>
<td>&nbsp;</td>
</tr>
<tr>
<th>Trd 16</th>
<td>1600\25M</td>
<td>4133\64M</td>
<td>1727\26M</td>
<td>115\1.7M</td>
<td>181\2.8M</td>
<td>&nbsp;</td>
</tr>
<tr>
<th>Trd 32</th>
<td>1939\30M</td>
<td>3952\61M</td>
<td>2080\32M</td>
<td>115\1.8M</td>
<td>182\2.8M</td>
<td>&nbsp;</td>
</tr>
</table>
<p><strong><font color="Teal">Form 2 &#8212; </font><font color="red">fsync per write request</font></strong></p>
<table border="1">
<tr>
<td>Req&#038;Trans/s</td>
<th>SeqWR</th>
<th>SeqRD</th>
<th>SeqReWr</th>
<th>RndRD</th>
<th>RndWR</th>
<th>RndReWr</th>
</tr>
<tr>
<th>Trd 1</th>
<td>33\543Kb</td>
<td>3842\60Mb</td>
<td>36\576Kb</td>
<td>110\1.7Mb</td>
<td>17\280Kb</td>
<td>31\510Kb</td>
</tr>
<tr>
<th>Trd 4</th>
<td>35\575Kb</td>
<td>4400\68Mb</td>
<td>34\556Kb</td>
<td>109\1.7Mb</td>
<td>26\418Kb</td>
<td>43\694Kb</td>
</tr>
<tr>
<th>Trd 8</th>
<td>34\545Kb</td>
<td>4267\66Mb</td>
<td>30\485Kb</td>
<td>111\1.7Mb</td>
<td>28\452Kb</td>
<td>47\756Kb</td>
</tr>
<tr>
<th>Trd 16</th>
<td>33\541Kb</td>
<td>4138\64Mb</td>
<td>34\545Kb</td>
<td>110\1.7Mb</td>
<td>30\481Kb</td>
<td>50\813Kb</td>
</tr>
<tr>
<th>Trd 32</th>
<td>33\532Kb</td>
<td>3942\61Mb</td>
<td>34\558Kb</td>
<td>110\1.7Mb</td>
<td>50\813Kb</td>
<td>65\1.0Mb</td>
</tr>
</table>
<p>一些缩写解释如下：</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">Req&amp;Trans/s<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">Request &amp; Transferred/sec</span>
<span style="color: #000099;">TRD</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">Threads</span>
<span style="color: #000099;">SEQ</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">sequency</span>
<span style="color: #000099;">RD</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">read</span>
<span style="color: #000099;">WR</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">Write</span>
<span style="color: #000099;">RND</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">Random</span>
<span style="color: #000099;">REWR</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">Read&amp;Write</span></pre></div></div>

<p>你看到的是一块非常普通的硬盘，他的顺序写也只有每秒54M，而现在好一些的硬盘都可以做到每秒80M以上的顺序写了。<br />
来看看 Amazon 的测试数据吧。</p>
<p><font size=3><strong>Amazon Micro Instance with Single Elastic Storage</strong></font></p>
<p><strong><font color="Teal">Form 3 &#8212; </font>fsync at end of test</strong></p>
<table border="1">
<tr>
<td>Req&#038;Trans/s</td>
<th>SeqWR</th>
<th>SeqRD</th>
<th>SeqReWr</th>
<th><font color="red">RndRD</font></th>
<th><font color="red">RndWR</font></th>
<th><font color="red">RndReWr</font></th>
</tr>
<tr>
<th>Trd 1</th>
<td>235\3.6M</td>
<td>1521\23M</td>
<td>256\4.0M</td>
<td><font color="red">1525\23M</font></td>
<td><font color="red">222\3.4M</font></td>
<td><font color="red">523\8.1M</font></td>
</tr>
<tr>
<th>Trd 4</th>
<td>247\3.8M</td>
<td>2480\38M</td>
<td>253\3.9M</td>
<td><font color="red">3138\49M</font></td>
<td><font color="red">1005\15M</font></td>
<td><font color="red">1698\26M</font></td>
</tr>
<tr>
<th>Trd 8</th>
<td>256\4.0M</td>
<td>3483\54M</td>
<td>251\3.9M</td>
<td><font color="red">8482\81M</font></td>
<td><font color="red">1691\26M</font></td>
<td><font color="red">1653\25M</font></td>
</tr>
<tr>
<th>Trd 16</th>
<td>251\3.9M</td>
<td><font color="red">5959\93M</font></td>
<td>243\3.7M</td>
<td><font color="red">1594\24M</font></td>
<td><font color="red">1888\29M</font></td>
<td><font color="red">1386\21M</font></td>
</tr>
<tr>
<th>Trd 32</th>
<td>251\3.9M</td>
<td><font color="red">6387\99M</font></td>
<td>260\4.0M</td>
<td><font color="red">5452\85M</font></td>
<td><font color="red">1303\20M</font></td>
<td>&nbsp;</td>
</tr>
</table>
<p>请注意看红色的部分，Amazon 磁盘的测试结果，写操作差的一塌糊涂，几乎和个U盘一样，但是只要有读操作！尤其是随机读取操作，数据就牛逼的一塌糊涂。其中随机读取最佳成绩为 5452\85M，而单个物理硬盘仅为 115\1.8M 。天壤之别！<br />
而且 RndWr 的写入比 SeqWr 要快了很多，这肯定是因为逻辑磁盘到物理磁盘之间存在数据分片。</p>
<p><strong>猜测：</strong><br />
1.Elastic Storage 和EC2 instance 之间很可能是走网络的。<br />
2.一定有数据冗余机制，但估计不是 RAID。<br />
3.有很大的 cache 在前面。很可能在用 SSD 做 cache。</p>
<p>这测试结果，你说好么，写入速度慢成这样…这鸟样也太过分了一点。你说他差么，随机读牛成这样… 没办法形容了。</p>
<p><font size=3><strong>Amazon Micro Instance with Raid 0 （2 disk）</strong></font></p>
<p><strong><font color="Teal">Form 4 &#8212; </font>fsync at end of test</strong></p>
<table border="1">
<tr>
<td>Req&#038;Trans/s</td>
<th>SeqWR</th>
<th>SeqRD</th>
<th>SeqReWr</th>
<th>RndRD</th>
<th><font color="red">RndWR</font></th>
<th><font color="red">RndReWr</font></th>
</tr>
<tr>
<th>Trd 1</th>
<td><font color="blue">194\3.0M</font></td>
<td>1440\22M</td>
<td>289\4.5M</td>
<td>1430\22M</td>
<td>188\2.9M</td>
<td>494\7.7M</td>
</tr>
<tr>
<th>Trd 4</th>
<td><font color="blue">182\2.7M</font></td>
<td>2631\41M</td>
<td>320\3.1M</td>
<td>3226\50M</td>
<td>650\10M</td>
<td>1248\19M</td>
</tr>
<tr>
<th>Trd 8</th>
<td><font color="blue">190\2.9M</font></td>
<td>3753\58M</td>
<td>297\3.2M</td>
<td>4330\67M</td>
<td>1612\25M</td>
<td><font color="red">2781\43M</font></td>
</tr>
<tr>
<th>Trd 16</th>
<td><font color="blue">182\2.8M</font></td>
<td>2895\45M</td>
<td>199\5.0M</td>
<td>3124\48M</td>
<td><font color="red">2121\33M</font></td>
<td><font color="red">2875\44M</font></td>
</tr>
<tr>
<th>Trd 32</th>
<td><font color="blue">190\2.9M</font></td>
<td>2465\38M</td>
<td>206\4.6M</td>
<td>4161\65M</td>
<td><font color="red">2158\33M</font></td>
<td><font color="red">3671\57M</font></td>
</tr>
</table>
<p>2 Disks Raid0 几乎和单硬盘没有什么太大变化，SeqWr 的数值全线微幅下降，可能是由于系统做软 Raid，系统层面有所开销所致。RndWr 在 16 线程和 32线程略微高一点。但也不是本质性提升。<br />
RndRW 8、16、32 有明显提高，但是很难判断是某个时间段 Amazon IO 比较空闲所致，还是 Raid0 的帮助。有一种可能是我做 md 的时候使用的默认 chunk 为 64，而 Amazon 本身的 chunk 比 64 大，所以我这么操作以后造成了更加分散的数据分布，所以 RndRW 会略好一点。但也很难解释为什么 RndRd 没有明显高起来。</p>
<p>同时我还做了 6 Disk Raid0 测试，由于数据和 2 Disk 实在是没啥差距，就不贴上来了。<br />
总的感觉 Amazon 上做 Raid 是件无意义的事情。这与国外一个人的测试[ <a href="http://af-design.com/blog/2009/02/27/amazon-ec2-disk-performance/">1</a> <a href="http://af-design.com/blog/2010/03/02/honesty-box-ebs-performance-revisited/">2</a> ]</a>相去甚远。不止是结论差异，性能也有差异，他在 6 Disk Raid0 的情况下 Seq Input 居然可以走到接近 110M 的速度，但是他的 Rnd Seek 在8Disk 的情况下最高也只走到 4000左右。我怀疑这是 Instance 差异导致，接下来看看 m1.large 的测试数据。</p>
<p><font size=3><strong>Amazon EC2 m1.large NoRaid</strong></font></p>
<p><strong><font color="Teal">Form 5 &#8212; </font>fsync at end of test</strong></p>
<table border="1">
<tr>
<td>Req&#038;Trans/s</td>
<th>SeqWR</th>
<th>SeqRD</th>
<th>SeqReWr</th>
<th>RndRD</th>
<th>RndWR</th>
<th>RndReWr</th>
</tr>
<tr>
<th>Trd 1</th>
<td>1084\16M</td>
<td>2330\36M</td>
<td>1149\17M</td>
<td>2134\33M</td>
<td>1124\17M</td>
<td>1378\21M</td>
</tr>
<tr>
<th>Trd 4</th>
<td>1058\16M</td>
<td>5445\85M</td>
<td>1113\17M</td>
<td>5586\87M</td>
<td>2039\31M</td>
<td>2904\45M</td>
</tr>
<tr>
<th>Trd 8</th>
<td>1053\16M</td>
<td>6509\101M</td>
<td>1147\17M</td>
<td>6569\102M</td>
<td>2112\33M</td>
<td>3054\47M</td>
</tr>
<tr>
<th>Trd 16</th>
<td>1026\16M</td>
<td>6195\96M</td>
<td>1122\17M</td>
<td>6486\101M</td>
<td>2144\33M</td>
<td>3802\59M</td>
</tr>
<tr>
<th>Trd 32</th>
<td>1034\16M</td>
<td>5985\93M</td>
<td>1158\18M</td>
<td>6490\101M</td>
<td>2149\33M</td>
<td>3859\60M</td>
</tr>
</table>
<p><strong><font color="Teal">Form 6 &#8212; </font><font color="red">fsync every 64 times write(1M)</font></strong></p>
<table border="1">
<tr>
<td>Req&#038;Trans/s</td>
<th>SeqWR</th>
<th>SeqRD</th>
<th>SeqReWr</th>
<th>RndRD</th>
<th>RndWR</th>
<th>RndReWr</th>
</tr>
<tr>
<th>Trd 1</th>
<td>1112\17M</td>
<td>2122\33M</td>
<td>1117\17M</td>
<td>2139\33M</td>
<td>1097\17M</td>
<td>1385\21M</td>
</tr>
<tr>
<th>Trd 4</th>
<td>1073\16M</td>
<td>5598\87M</td>
<td>1097\17M</td>
<td>5759\89M</td>
<td>2263\35M</td>
<td>3179\49M</td>
</tr>
<tr>
<th>Trd 8</th>
<td>1064\16M</td>
<td>6453\100M</td>
<td>1122\17M</td>
<td>6563\102M</td>
<td>2164\33M</td>
<td>3740\58M</td>
</tr>
<tr>
<th>Trd 16</th>
<td>1118\17M</td>
<td>6511\101M</td>
<td>1138\17M</td>
<td>6607\103M</td>
<td>2060\32M</td>
<td>3763\58M</td>
</tr>
<tr>
<th>Trd 32</th>
<td>1083\16M</td>
<td>6715\1044M</td>
<td>1173\18M</td>
<td>6713\104M</td>
<td>1997\31M</td>
<td>3880\60M</td>
</tr>
</table>
<p><strong><font color="Teal">Form 7 &#8212; </font><font color="red">fsync per write request</font></strong></p>
<table border="1">
<tr>
<td>Req&#038;Trans/s</td>
<th>SeqWR</th>
<th>SeqRD</th>
<th>SeqReWr</th>
<th>RndRD</th>
<th>RndWR</th>
<th>RndReWr</th>
</tr>
<tr>
<th>Trd 1</th>
<td>353\5.5M</td>
<td>1808\28M</td>
<td>371\5.8M</td>
<td>2017\31M</td>
<td>289\4.5M</td>
<td>677\10M</td>
</tr>
<tr>
<th>Trd 4</th>
<td>352\5.5M</td>
<td>5003\78M</td>
<td>395\6.1M</td>
<td>5256\82M</td>
<td>1237\19M</td>
<td>1634\25M</td>
</tr>
<tr>
<th>Trd 8</th>
<td>350\5.4M</td>
<td>6071\94M</td>
<td>388\6.0M</td>
<td>5825\91M</td>
<td>1589\24M</td>
<td>2879\44M</td>
</tr>
<tr>
<th>Trd 16</th>
<td>355\5.5M</td>
<td>6420\100M</td>
<td>360\5.6M</td>
<td>6172\96M</td>
<td>1607\25M</td>
<td>3104\48M</td>
</tr>
<tr>
<th>Trd 32</th>
<td>349\5.4M</td>
<td>6507\101M</td>
<td>374\5.8M</td>
<td>6248\97M</td>
<td>1703\26M</td>
<td>3156\49M</td>
</tr>
</table>
<p><font size=3><strong>Amazon EC2 m1.large 6 Disk Raid 0</strong></font></p>
<p><strong><font color="Teal">Form 8 &#8212; </font><font color="red">fsync per write request</font></strong></p>
<table border="1">
<tr>
<td>Req&#038;Trans/s</td>
<th>SeqWR</th>
<th>SeqRD</th>
<th>SeqReWr</th>
<th>RndRD</th>
<th>RndWR</th>
<th>RndReWr</th>
</tr>
<tr>
<th>Trd 1</th>
<td>164\2.5M</td>
<td>1605\25M</td>
<td>225\3.5M</td>
<td>1338\20M</td>
<td>238\3.7M</td>
<td>280\4.3M</td>
</tr>
<tr>
<th>Trd 4</th>
<td>177\2.7M</td>
<td>3707\57M</td>
<td>242\3.7M</td>
<td>4730\73M</td>
<td>649\10M</td>
<td>671\10M</td>
</tr>
<tr>
<th>Trd 8</th>
<td>176\2.7M</td>
<td>5043\78M</td>
<td>237\3.7M</td>
<td>7538\117M</td>
<td>948\14M</td>
<td>1083\16M</td>
</tr>
<tr>
<th>Trd 16</th>
<td>163\2.5M</td>
<td>5927\92M</td>
<td>233\3.6M</td>
<td>9168\143M</td>
<td>1006\15M</td>
<td>1273\19M</td>
</tr>
<tr>
<th>Trd 32</th>
<td>152\2.3M</td>
<td>9210\143M</td>
<td>240\3.7M</td>
<td>10025\156M</td>
<td>573\8.9M</td>
<td>1369\21M</td>
</tr>
</table>
<p>根据这些数据可以得到以下结论：</p>
<p>1. Large 比 Micro 在 IO 方面性能好。<br />
2. RAID 无意义。<br />
3. 瓶颈在连续写。<br />
4. Amazon 机器即使在 fsync per write request 的情况下，随机写也可以达到 1000/s ，而随机读在 5000-6000/s。其随机性能比得上 SSD 了。<br />
5. 由于 MySQL Dirty Page 有两次写，两次写空间为 2M，每写1M sync 一次，所以上面专门有 64 times sync 的测试数据。其连续写数据，我觉得可以做为 Amazon Large MySQL 写入瓶颈数值参考。<br />
6. 不要轻易相信别人的神化！</p>
<p>很多 MySQL 的参数设置还需要结合很多信息才能确定，单靠磁盘监测还不够。以后再开别的文章来探讨吧。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://latteye.com/2011/12/amazon-ec2-disk-performence.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Linux 上搭建 Mac TimeMachine Server</title>
		<link>http://latteye.com/2011/12/mac-timemachine-server-base-on-arch-linux.html</link>
		<comments>http://latteye.com/2011/12/mac-timemachine-server-base-on-arch-linux.html#comments</comments>
		<pubDate>Fri, 09 Dec 2011 07:58:36 +0000</pubDate>
		<dc:creator>latteye</dc:creator>
				<category><![CDATA[Life ㄆ 自己生活]]></category>
		<category><![CDATA[arch]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[timemachine]]></category>

		<guid isPermaLink="false">http://latteye.com/?p=1385</guid>
		<description><![CDATA[在接触 Mac TimeMachine 之前已经用过了 Windows Home Server。HomeServer 的备份效果几乎和 TimeMachine 是一样的。不过你可以更加灵活的定制自己想要备份的频率。虽然 Mac 备份的频率不可调节，但也足够了： 也就是说你会有 24+29(+1)+N月*4 份快照。如果 TimeMachine 的备份原理和 HomeServer 是一样的话，完全不必担心容量问题。基于Block层面的增量备份可是非常小的。 首次备份可能会占用你一点时间，但随后的增量备份快到你几乎感觉不到。除非你突然增加了50G的文件。对于Macbook Air的小硬盘来说，突然有这么大的文件我也不会留在笔记本上。 同时几个虚拟机文件转移到一个移动硬盘上，在家里也基本上一直插着，外出根据需要咯。 话说，进入到 TimeMachine 里面的效果确实很赞啊，苹果做的东西的确蛮好看的，屏幕右侧就是一个时间轴，选取一点就会显示出那个时间点的 Home 目录： Finder 在 Finder 中会多出来一个 TimeMachine 卷： 在这个卷中，可以浏览到自己所有的快照节点,这些都是我每小时的节点： 值得参考的文章： HowTo: Make Ubuntu A Perfect Mac File Server And Time Machine Volume 自建基于 Linux 的 Time Capsule 服务 在 Arch [...]
Related posts:<ol>
<li><a href='http://latteye.com/2007/12/macmenu-in-arch-gnome.html' rel='bookmark' title='在 Arch Linux Gnome 下使用 Mac Menu'>在 Arch Linux Gnome 下使用 Mac Menu</a></li>
<li><a href='http://latteye.com/2007/08/linux-server-hacks-volume-two.html' rel='bookmark' title='Linux Server Hacks Volume Two'>Linux Server Hacks Volume Two</a></li>
<li><a href='http://latteye.com/2007/03/%e9%80%9a%e8%bf%87%e7%bd%91%e7%bb%9c%e5%ae%89%e8%a3%85-linux-%ef%bc%88-centos-%ef%bc%89%e7%b3%bb%e7%bb%9f.html' rel='bookmark' title='通过网络安装 Linux （ CentOS ）系统'>通过网络安装 Linux （ CentOS ）系统</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>在接触 Mac TimeMachine 之前已经用过了 Windows Home Server。HomeServer 的备份效果几乎和 TimeMachine 是一样的。不过你可以更加灵活的定制自己想要备份的频率。虽然 Mac 备份的频率不可调节，但也足够了：<span id="more-1385"></span></p>
<p><img src="http://pic.yupoo.com/latteye/BzWQV20V/medish.jpg" alt="TimeMachine" /></p>
<p>也就是说你会有 24+29(+1)+N月*4 份快照。如果 TimeMachine 的备份原理和 HomeServer 是一样的话，完全不必担心容量问题。基于Block层面的增量备份可是非常小的。<br />
首次备份可能会占用你一点时间，但随后的增量备份快到你几乎感觉不到。除非你突然增加了50G的文件。对于Macbook Air的小硬盘来说，突然有这么大的文件我也不会留在笔记本上。</p>
<p>同时几个虚拟机文件转移到一个移动硬盘上，在家里也基本上一直插着，外出根据需要咯。</p>
<p>话说，进入到 TimeMachine 里面的效果确实很赞啊，苹果做的东西的确蛮好看的，屏幕右侧就是一个时间轴，选取一点就会显示出那个时间点的 Home 目录：</p>
<p><a href="http://www.yupoo.com/photos/latteye/83821744/"><img src="http://pic.yupoo.com/latteye/BzWW02Nd/medish.jpg" alt="TimeMachine" /></a></p>
<p><strong>Finder</strong><br />
在 Finder 中会多出来一个 TimeMachine 卷：</p>
<p><img src="http://pic.yupoo.com/latteye/BzX47V1j/medish.jpg" alt="" /></p>
<p>在这个卷中，可以浏览到自己所有的快照节点,这些都是我每小时的节点：</p>
<p><img src="http://pic.yupoo.com/latteye/BzX49qJR/medish.jpg" alt="" /></p>
<p>值得参考的文章：<br />
<a href="http://www.kremalicious.com/2008/06/ubuntu-as-mac-file-server-and-time-machine-volume/"><br />
HowTo: Make Ubuntu A Perfect Mac File Server And Time Machine Volume</a><br />
<a href="http://www.gracecode.com/archives/3057/">自建基于 Linux 的 Time Capsule 服务</a></p>
<p>在 Arch Linux 上磕磕碰碰遇到的问题：</p>
<p><strong>1.备份时遇到 “网络备份磁盘不支持所要求的 AFP 功能” 报错</strong></p>
<p>我尝试了多种配置文件，最终能正常工作的配置文件如下：</p>
<p>afpd.conf</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">- -tcp -noddp -uamlist uams_dhx.so,uams_dhx2.so -nosavepassword</pre></div></div>

<p>AppleVolumes.default:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">/media/main/TimeMachine TimeMachine allow:latteye cnidscheme:cdb options:tm,usedots,upriv</pre></div></div>

<p>netatalk.conf</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;"><span style="color: #000099;">ATALKD_RUN</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">no</span>
<span style="color: #000099;">PAPD_RUN</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">no</span>
<span style="color: #000099;">TIMELORD_RUN</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">no</span>
<span style="color: #000099;">A2BOOT_RUN</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">no</span>
<span style="color: #000099;">CNID_METAD_RUN</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">yes</span>
<span style="color: #000099;">AFPD_RUN</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">yes</span></pre></div></div>

<p><strong>2. netatalk 服务缺少 atalkd 执行文件</strong></p>
<p>在 Arch 上打了N次包都不见 atalkd 二进制文件，搞不清楚什么原因。最后自己在 netatalk 2.2.1 源码目录下找到 atalkd 源码目录 make 出来拷贝到系统中。</p>
<p>Related posts:</p><ol>
<li><a href='http://latteye.com/2007/12/macmenu-in-arch-gnome.html' rel='bookmark' title='在 Arch Linux Gnome 下使用 Mac Menu'>在 Arch Linux Gnome 下使用 Mac Menu</a></li>
<li><a href='http://latteye.com/2007/08/linux-server-hacks-volume-two.html' rel='bookmark' title='Linux Server Hacks Volume Two'>Linux Server Hacks Volume Two</a></li>
<li><a href='http://latteye.com/2007/03/%e9%80%9a%e8%bf%87%e7%bd%91%e7%bb%9c%e5%ae%89%e8%a3%85-linux-%ef%bc%88-centos-%ef%bc%89%e7%b3%bb%e7%bb%9f.html' rel='bookmark' title='通过网络安装 Linux （ CentOS ）系统'>通过网络安装 Linux （ CentOS ）系统</a></li>
</ol>]]></content:encoded>
			<wfw:commentRss>http://latteye.com/2011/12/mac-timemachine-server-base-on-arch-linux.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Redis Persistence</title>
		<link>http://latteye.com/2011/11/redis-persistence.html</link>
		<comments>http://latteye.com/2011/11/redis-persistence.html#comments</comments>
		<pubDate>Sun, 27 Nov 2011 14:53:53 +0000</pubDate>
		<dc:creator>latteye</dc:creator>
				<category><![CDATA[Work / 努力工作]]></category>
		<category><![CDATA[aof]]></category>
		<category><![CDATA[rdb]]></category>
		<category><![CDATA[redis]]></category>

		<guid isPermaLink="false">http://latteye.com/?p=1346</guid>
		<description><![CDATA[本文由 latteye 翻译自 Redis 文档 Redis Persistence。此文比较详细的介绍了 Redis 的两种持久化方式，是 Linux SA 了解 Redis 的必读资料.同时此文整理在 latteye doc 页面。本人能力有限，英文水平不佳，翻译有错误的地方欢迎指出。 Redis 为持久化（latteye注：可以简单的理解为存储）提供了不同的方案： RDB 持久化提供了以某个周期时间为节点，对数据快照的方案。 AOF 持久化方案记录了所有服务器接收到的指令。并可以在服务器启动时将指令重新加载，从而重构原始的数据库。Redis 用和它协议相同的方式来记录这些指令，同时命令的记录是不断添加的（append-only）。当 log 过于庞大时 Redis 可以在后台对其进行重写。 如果你只希望数据库运行的时候保存数据，你可以关闭持久化选项。 AOF 和 RDB 可以在一个实例中合起来用。注意，在这种情况下，当服务器重启时，是由 AOF 来重构数据库的。因为 AOF 对数据的保障性更加可靠。 最重要的是理解 RDB 和 AOF 之间的区别，从而能权衡两者。让我们先来看 RDB 吧： RDB 的优势 RDB 是一种以时间点为基准(point-in-time)且使用单文件(single-file)的数据重现方式。RDB 文件非常适合用来备份。比如你希望在最近的24小时，每小时对数据做一次快照，且最近30天，每天保留一份快照。RDB 让你非常方便的从灾难中恢复数据到任意一个时间点。 RDB 非常适合灾难恢复。单文件存储的方式非常适合将文件传输到远程的数据中心，或者备份在 Amazon S3 上（最好加密哦）。 [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>本文由 <a href="http://latteye.com"> latteye</a> 翻译自 Redis 文档 <a href="http://redis.io/topics/persistence">Redis Persistence</a>。此文比较详细的介绍了 Redis 的两种持久化方式，是 Linux SA 了解 Redis 的必读资料.同时此文整理在 <a href="http://latteye.com/doc">latteye doc 页面</a>。本人能力有限，英文水平不佳，翻译有错误的地方欢迎指出。<span id="more-1346"></span></p>
<p>Redis 为持久化（latteye注：可以简单的理解为存储）提供了不同的方案：</p>
<ul>
<li>RDB 持久化提供了以某个周期时间为节点，对数据快照的方案。</li>
<li>AOF 持久化方案记录了所有服务器接收到的指令。并可以在服务器启动时将指令重新加载，从而重构原始的数据库。Redis 用和它协议相同的方式来记录这些指令，同时命令的记录是不断添加的（append-only）。当 log 过于庞大时 Redis 可以在后台对其进行重写。</li>
<li>如果你只希望数据库运行的时候保存数据，你可以关闭持久化选项。</li>
<li>AOF 和 RDB 可以在一个实例中合起来用。注意，在这种情况下，当服务器重启时，是由 AOF 来重构数据库的。因为 AOF 对数据的保障性更加可靠。</li>
</ul>
<p>最重要的是理解 RDB 和 AOF 之间的区别，从而能权衡两者。让我们先来看 RDB 吧：</p>
<p><strong><font size=4>RDB 的优势</font></strong></p>
<ul>
<li>RDB 是一种以时间点为基准(point-in-time)且使用单文件(single-file)的数据重现方式。RDB 文件非常适合用来备份。比如你希望在最近的24小时，每小时对数据做一次快照，且最近30天，每天保留一份快照。RDB 让你非常方便的从灾难中恢复数据到任意一个时间点。</li>
<li>RDB 非常适合灾难恢复。单文件存储的方式非常适合将文件传输到远程的数据中心，或者备份在 Amazon S3 上（最好加密哦）。</li>
<li>RDB 可以让性能最大化。Redis 父进程只需要派生出一个子进程来管理即可，其父进程永远都不需要执行磁盘 I/O 相关的操作。</li>
<li>在你的数据库文件较大时，RDB 提供比 AOF 更快的重启速度。</li>
</ul>
<p><strong><font size=4>RDB 的劣势</font></strong></p>
<ul>
<li>如果你希望在 Redis 异常退出时（比如断电了）最小化数据损失，Redis 并不是你最好的选择。你可以在部署了RDB的机器上配置不同的保存点（对于实例来说至少等待5分钟且写入数据次数超过100次，不过你可以设置多个保存点）。无论如何，你通常会每五分钟创建一个或多个快照，所有当 Redis 非正常关闭的时候你应该会丢失几分钟的数据。</li>
<li>由于需要经常操作磁盘，RDB 会经常 fork()出一个子进程。如果你的数据库文件很大的话，Fork()占用比较多的时间，并且可能会影响 Redis 暂停服务一段时间（millisecond 级别），如果你的数据库超级大并且你的CPU比较弱，有可能是会达到一秒。AOF 同样需要 fork()，但你可以调整重写的频率来协调性能和数据的保障性。 </li>
</ul>
<p><strong><font size=4>AOF 的优势</font></strong></p>
<ul>
<li>在 Redis 使用 AOF 更加持久化：你可以使用不同的 fsync 策略：完全不做 fsync，每秒 fsync，每一个请求 fsync。使用默认的每秒 fsync 模式时，性能依旧是非常好的。（主进程在后台没有 fsync 在执行的时候会尽量的做写操作），而且你只会丢失最多一秒的数据。</li>
<li>AOF 日志是一个不断添加的日志（append only），所有它不可以搜索，同时即使在机器电源故障的情况下日志也不会损坏。即使有一条命令写到一半的时候失败了，redis-check-aof 工具也可以很方便的修复日志。</li>
<li>当日志过大的时候，Redis 可以在后台重写 AOF 日志。整个重写过程是安全的，当 Redis 创建新的准备新的 log 文件时，它依旧往旧的日志里面写入数据。同时，它会根据当前的数据库创建一个新的、最小的日志文件。当这些都完成时，Redis 将两个日志文件交换，并将些的log记录在新的文件上。</li>
<li>AOF 用一种简单的格式逐一记录了所有的操作。你甚至可以方便的导出一个 AOF 文件。如果你在一台实例上误输入了 FLUSHALL 命令，在日志文件被重写之前，你可以简单的停止你的服务器，在日志文件中删除最后的 FLUSHALL 命令，然后重启 Redis，之前被删除的数据依旧在那里。</li>
</ul>
<p><strong><font size=4>AOF 的劣势</font></strong></p>
<ul>
<li>对于等量的数据库来说 AOF 产生的文件比 RDB 要大。</li>
<li>根据 fsync 策略的不同，AOF 有可能比 RDB 要慢。通常使用每秒 fsync 一次的性能还是比较高的。如果你关闭 fsync， AOF 的性能即使在高负载下应该和 RDB 一样高。当然，在高磁盘负载时还是 RDB 相对能提供比较稳定的延时效果。</li>
<li>曾经有一些命令（for instance there was one involving blocking commands like BRPOPLPUSH）会导致一些罕见的 bug &#8212; AOF 在启动的时候会不重新加载原有数据。这样的 bug 很少见，我们在一套测试环境中进行了测试。我们自动创建了一些大量的随机数据，然后重新加载数据库，看看一切是否正常。不过 RDB 环境下面机会不会出现这种 bug。让我们明确的看一下：Redis AOF 通过一种不断增长式的方式来更新数据。而 RDB 在一个基础上不断的创造快照，这种方式更加强壮。但是 1) 需要注意的是，Redis 每一次重写 AOF 时，都是从一个数据文件中真实的数据重写而来。相对不断的添加数据到 AOF 文件（or one rewritten reading the old AOF instead of reading the data in memory），这种方式产生 bug 的几率更小。2）在实际应用中从来没有收到过 AOF 损坏的报告。</li>
</ul>
<p><strong><font size=4>OK ，到底选择什么呢？</font></strong></p>
<p>通常，如果你要和 PostgreSQL 所提供的数据保障性相比较，那么建议你同时使用两种持久化方式。</p>
<p>如果你非常在意你的数据，但是也还可以接受灾难带来的几分钟的数据丢失，那么你可以仅使用 RDB。</p>
<p>很多用户仅使用了 AOF，但是我们建议，既然 RDB 可以时不时的给数据做个完整的快照，并且提供更快的重启，而且在某些情况下 bug 也要少，你最好还是使用 RDB。</p>
<p>注：综合以上原因，我们希望可以在未来（长远计划）统一 AOF 和 RDB 成一种持久化模式。</p>
<p>下面的章节将以实例来介绍两种持久化方式的更多细节。</p>
<p><strong><font size=4>快照</font></strong></p>
<p>默认情况下，Redis 在磁盘上以二进制格式保存数据快照，名为 dump.rdb。你可以配置 Redis 每 N 秒且至少有 M 次 数据修改则保存一次数据，或者你可以手动通过 SAVE 或者 BGSAVE 命令来执行保存。</p>
<p>比如，这个配置会让 Redis 每 60 秒且至少有 1000 次 key 修改，则保存一次数据：</p>
<p><code>save 60 1000</code></p>
<p>这种策略被成为 <em>快照(snapshotting)</em></p>
<p><strong><font size=4>它怎么工作？</font></strong></p>
<p>当Redis需要将数据导出到磁盘时，发生了以下事情：</p>
<ul>
<li>Redis 派生出一个子进程。我们现在有一个子进程和一个父进程。</li>
<li>子进程开始将数据写入一个临时的 RDB 文件。</li>
<li>当子进程写完新的 RDB 文件后，用新的 RDB 文件替换旧的。</li>
</ul>
<p>这种工作方式允许 Redis 使用到 copy-on-wirite 带来的优势。</p>
<p><strong><font size=4>Append-only 文件</font></strong></p>
<p>快照的持久化非常可靠。如果你的 Redis 突然停止、你的电源突然坏了、或者你意外的 kill -9 了你的进程，最后写入 Redis 的那些数据都会丢失。对某些应用来说，这可能不是什么大问题，还有很多的方式来保障数据可靠性，在那些情况下 Redis 并不是很好的选择。</p>
<p>append-only 文件是另一个可以提供完全数据保障的方案。这种技术自 1.1 版本启用。</p>
<p>你可以在配置中打开 AOF 功能：</p>
<p><code>appendonly yes<code></p>
<p>配置以后，只要是 Redis 接收到的会修改数据库的命令就会被记录在 AOF 文件中。当你重启 Redis 之后，它会重复 AOF 中的指令从而来重现数据最新的状态。</p>
<p><strong><font size=4>日志重写</font></strong></p>
<p>和你想的一样，AOF 文件会在操作过程中变得越来越大。比如，如果你做一百次加法计算，最后你只会在数据库里面得到最终的数值，但是在你的 AOF 里面会存在 100 次记录。其中 99 条记录对最终的结果是无用的。</p>
<p>所以 Redis 支持一个很有趣的功能：他可以在不影响服务的前提下在后台重构 AOF 文件。当你输入 BGREWRITEAOF 命令时，Redis 会在内存中按最简短的排序整理所有的指令。如果你在使用 Redis 2.2 你需要是不是的跑一下 BGREWRITEAOF 命令。而 Redis 2.4 已经支持自动进行重新工作(更多信息请查看 2.4 文档。)</p>
<p><strong><font size=4>Append Only 文件到底有多可靠?</font></strong></p>
<p>你可以配置 Redis 如何将数据 fsync 到磁盘上。有以下几种选项。</p>
<ul>
<li>每当有命令请求时，fsync。非常安全，非常非常慢。</li>
<li>每秒做一次fsync。足够快了（在 2.4 版本中几乎和快照模式一样快。）,而在遇到灾难时，你可能会丢失最近1秒的数据。
<li>永远不做 fsync，仅仅只是把数据放在系统中，非常快，但是却不安全的方式</li>
</ul>
<p>建议的（且默认的）模式是每秒同步一次。这是坚固速度和安全的方式。一有命令就记录的方式在以前是很慢的(尽管在2.0版本中有所提升) - 没什么办法让 fsync 更快了。</p>
<p><strong><font size=4>当 AOF 文件损坏时，应该怎么做？</font></strong></p>
<p>AOF 在服务器崩溃的时候是有可能损坏的（这永远没办法解决），Redis 无法加载已经损坏的文件。如果你遇到了这种情况，你可以通过以下的步骤来修复问题：</p>
<ul>
<li>给AOF文件做个备份。</li>
<li>用 Redis 随身带的 redis-check-aof 命令来修复原始文件：</li>
<p><code>$ redis-check-aof --fix "filename"</code></p>
<li>用 diff -u 来比较两个文件之间的区别(非必须)</li>
<li>用修复过的文件来重启服务器。</li>
</ul>
<p><strong><font size=4>它如何工作的？</font></strong></p>
<p>日志重写用了和快照一样的 copy-on-write 技术。以下是他工作的方式：</p>
<p>Redis 派生出一个子进程，于是我们一个父进程和一个子进程了。</p>
<ul>
<li>子进程开始在一个临时文件写入 AOF 信息。</li>
<li>父进程将所有的新指令积蓄在内存中(在同一时刻，它也将指令记录在了老 AOF 文件中，这样即使重写过程失败了，我们也是安全的。)
<li>当子进程重写完文件之后，父进程会获取到一个信号，然后将内存中积累的数据由子进程写入到文件中去。</li>
<li>搞定！现在Redis 自动将文件名修改，以后就将数据添加到新文件中了。</li>
</ul>
<p><strong><font size=4>如果我正在使用 RDB 快照，怎么才能切入到AOF呢？</font></strong></p>
<p>在2.2和2.0版本中，这个操作略有不同。当然，我相信你可以猜到，2.2中的操作要简单一些，且不要求重启。</p>
<p><strong><font size=3>Redis >= 2.2</font></strong></p>
<ul>
<li>给你最新的 dump.rdb 文件做一个备份。</li>
<li>将这个备份文件保存到一个安全的地方。</li>
<li>输入下面两个命令：</li>
<li>redis-cli config set appendonly yes</li>
<li>redis-cli config set save ""</li>
<li>确认一下你的数据库 key 的数量没有变化。</li>
<li>确认一下新的记录已经记录到了正确的文件。</li>
</ul>
<p>第一个 CONFIG 命令启用了 Append Only 文件。Redis 会按照顺序先先初始化一个文件，接着打开这个文件给 AOF 写入，然后会将所有的请求写入 AOF 文件。</p>
<p>第二个 CONFIG 命令 是用来关闭快照持久化模式。这不是必须的，如果你想要，你可以同时使用两种持久化模式。</p>
<p>重要：记得在你的 redis.conf 文件中开启 AOF，不然的话一旦你重启服务器，服务器会按照以前的配置工作了。</p>
<p><strong><font size=3>Redis 2.0</font></strong></p>
<ul>
<li>备份你最新的 dump.rdb 文件。</li>
<li>将备份文件放到安全的地方。</li>
<li>停止一切数据库写入操作。</li>
<li>执行 redis-cli bgrewriteaof 命令。这将创建一个 append only 文件.</li>
<li>当 Redis 完成创建 AOF dump 文件之后停止服务器。</li>
<li>编辑 redis.conf 文件以开启 AOF 持久化选项。</li>
<li>重启服务器。</li>
<li>确认你的数据没有少。</li>
<li>确认所有请求已经记录到了正确的 AOF 文件。</li>
</ul>
<p><strong><font size=4>整合 RDB 和 AOF 两种持久化模式</font></strong></p>
<p>Redis >= 2.4 确保了在 RDB 做快照的过程中不会触发一个 AOF 重写动作，反之亦然。这避免了两种持久化同时触发高I/O的工作。</p>
<p>当快照正在处理时，如果用户手动执行了 BGREWRITEAOF 命令，服务器会立刻返回一个 OK。这表示重写动作已经在排队，当快照完成之后就会执行 AOF 重写。</p>
<p>如果你同时启用了 AOF 和 RDB，在 Redis 重启的时候，系统会使用 AOF 文件来重构数据库。这是因为 AOF 相对更加可靠。</p>
<p><strong><font size=4>备份Redis数据</font></strong></p>
<p>在开始本章之前，请先读读下面这句话：一定要备份你的数据库。磁盘损坏，实例莫名其妙的消失，这相当于：将你大量的数据都写入到 /dev/null。</p>
<p>Redis 是一款非常易于备份的数据库 -- 你可以在 Redis 运行的时候拷贝 RDB 文件。RDB 文件绝对不会在拷贝的时候被修改，在拷贝的过程中，他会使用一个临时的文件名。只有在快照完全结束时，才会用 rename(2) 将其改为最终的名字。(and while it gets produced it uses a temporary name and is renamed into its final destination atomically using rename(2) only when the new snapshot is complete.)</p>
<p>这表示在服务器运行的时候拷贝RDB文件是一件绝对安全的事情。以下是我们的建议：</p>
<ul>
<li>用 crontab 每小时为数据库创建一次快照，另在别处保留每日快照。</li>
<li>每次 crontab 执行的时候，用 find 命令寻找老的快照并删除。保留最近48小时的每小时快照，保留1-2个月的每日快照。用日期以及时间信息来命名这些文件。</li>
<li>每天至少将这些文件转移一次到别的机房，至少转移出那台物理机器。</li>
</ul>
<p><strong><font size=4>灾难恢复</font></strong></p>
<p>在此文中灾难恢复可以理解为和备份一样的工作，外加将备份的文件转移至其他不同的机房。这样即使在 Redis 所在的机房遇到严重的灾难时，你依旧可以使用它的快照来恢复数据。</p>
<p>由于大多数 Redis 的用户都处于起步阶段，估计并没有太多的钱花在灾难恢复上，我们来看看比较有趣且便宜的方案吧：</p>
<p>Amazon S3 和其他类似的服务非常作为您的灾难恢复系统。你只要将你的每日备份简单的放在 S3 的加密区域。你可以使用 gpg -c 来加密你的数据。并且确保将密码保存在多个安全的地方（可以分发给你公司里比较重要的人）。我们建议同时使用多个外部存储服务来保障数据安全。</p>
<p>使用 scp (ssh 的一部分) 将数据传输到可信的服务器。下面是个简单而且安全的方式：在距离你很远的地方弄台VPS，装上 ssh，最好是一个仅用密钥登陆且无密码的配置。这样就可以很方便的自动传输备份文件了。最好在不同的商家那里多买点 VPS。</p>
<p>请注意！如果你没有按照正确的方式部署，这种方式还是很容易失败的。至少在完成传输以后请用 SHA1 sum 验证文件是否正确。<br />
<font color="#FFFFFF">本文由 latteye 翻译，文章永久地址为 http://latteye.com/2011/11/redis-persistence.html</font></p>
<p>另外你也需要一个监控系统来检查文件的传输是否正确。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://latteye.com/2011/11/redis-persistence.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Redis Replication</title>
		<link>http://latteye.com/2011/11/redis-replication.html</link>
		<comments>http://latteye.com/2011/11/redis-replication.html#comments</comments>
		<pubDate>Thu, 24 Nov 2011 10:30:04 +0000</pubDate>
		<dc:creator>latteye</dc:creator>
				<category><![CDATA[Work / 努力工作]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[replication]]></category>

		<guid isPermaLink="false">http://latteye.com/?p=1332</guid>
		<description><![CDATA[Redis replication(复制)是一款基于 master-slave （主从）机制且易于配置和使用的 Replication。master-slave 则表示 slave 服务器可以成为 master 服务器额外的数据备份。以下是关于 Redis Replication 非常重要的知识点： 一个 master 可以有多台 slave。 Slave 机器可以被其他的 Slave 服务器连接。除了多台 Slave 可以连接到同一台 Master，多台 Slave 也可以连接到同一台 Slave 机器。 在 master 端 Redis replication 是非阻塞的,这表示 Master 即使在执行和其他 Slave 的同步命令时，依旧可以完成别的查询服务。 在 Slave 端，Replication 也是非阻塞的。如果你在 redis 的配置文件 redis.conf 中做过配置，Slave 在没有完成一次同步时，依旧可以使用旧版本的数据来提供查询服务。另外你还可以配置 Slave，当 Slave 和 Master 的连接断开时，若有客户端查询，则返回错误。 Replication 可被用于解决性能问题和简单的数据冗余问题。当你有大量的 read-only [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>Redis replication(复制)是一款基于 master-slave （主从）机制且易于配置和使用的 Replication。master-slave 则表示 slave 服务器可以成为 master 服务器额外的数据备份。以下是关于 Redis Replication 非常重要的知识点：<span id="more-1332"></span></p>
<ul>
<li>一个 master 可以有多台 slave。</li>
<li>Slave 机器可以被其他的 Slave 服务器连接。除了多台 Slave 可以连接到同一台 Master，多台 Slave 也可以连接到同一台 Slave 机器。</li>
<li>在 master 端 Redis replication 是非阻塞的,这表示 Master 即使在执行和其他 Slave 的同步命令时，依旧可以完成别的查询服务。</li>
<li>在 Slave 端，Replication 也是非阻塞的。如果你在 redis 的配置文件 redis.conf 中做过配置，Slave 在没有完成一次同步时，依旧可以使用旧版本的数据来提供查询服务。另外你还可以配置 Slave，当 Slave 和 Master 的连接断开时，若有客户端查询，则返回错误。</li>
<li>Replication 可被用于解决性能问题和简单的数据冗余问题。当你有大量的 read-only 请求时，多台 Slave 可以很好的为你的系统分担压力。比如繁重的 SORT 操作可以分配给 Slave 来完成。</li>
<li>Replication 可以避免在 Master 端执行 save 指令，只要在 Master 端的 redis.conf 文件注释掉 “save” 即可。接着将某台 Slave 配置为实时 save。</li>
</ul>
<p><strong>Redis replication 是如何工作的？</strong></p>
<p>如果你配置好一台 Slave，连接建立之后它会发送一个 SYNC 命令。而本次连接是首次连接还是再连接无关紧要。</p>
<p>接着 master 开始后台 save，并且开始整理所有会影响到数据库的新命令。当后台 save 完成后，master 将保存在硬盘上的数据文件加载到内存中并发送给 slave。Master 会将所有累计的和新的会修改到数据库的命令都发给 Slave。这个过程被设计成使用命令流的形式，且和 Redis 自己的协议采用同一种格式。</p>
<p>你可以用 telnet 自己试试看。当 Redis 在工作的时候 telnet 到它的端口，然后打入 SYNC 命令。这时候你会看到一大块的数据传输，接着你会看到所有 master 接受到的命令会在 telnet 回话中重复。</p>
<p>当 Slave 和 Master 的连接断开后，Slave 可以自己重连至 Master。当 Master 收到多个并发的 Slave 同步请求时，它仅在后台用一个 save 进程来给多个 Slave 提供服务。</p>
<p>当 Master 和 Slave 在连接中断后重连上了，他们需要做一个完整的同步。</p>
<p><strong>配置</strong></p>
<p>Replication 的配置非常简单: 只要把下面这行配置加入 Slave 的配置文件:</p>
<p><code>slaveof 192.168.1.1 6379</code></p>
<p>当然你需要把 192.168.1.1 6379 换成你 Master 的地址和端口。 或者你可以执行 SLAVEOF 命令来触发 master 和 slave 来做一次同步。</p>
<p>配置 Slave 和 Master 之间的验证</p>
<p>如果你的 Master 需要一个密码验证。Slave 端的配置也非常简单。</p>
<p>用 redis-cli 在已经开启的 Slave 实例上执行命令：</p>
<p><code>config set masterauth
<password></code></p>
<p>把下面内容加入配置文件，如果你想要永久保存密码的话：<br />
<font color="#FFFFFF">本文由 latteye 翻译，文章永久地址为 http://latteye.com/2011/11/redis-replication.html</font></p>
<p><code>masterauth “password”</code><br />
请将双引号替换为大于小于号。</p>
<p>原文地址 <a href="http://redis.io/topics/replication">Redis Replication</a>,此译文整理于 <a href="http://latteye.com/doc" target="_blank">latteye doc 页面</a>。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://latteye.com/2011/11/redis-replication.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>十五分钟介绍 Redis 数据结构</title>
		<link>http://latteye.com/2011/11/15-minutes-introduction-to-redis-data-types.html</link>
		<comments>http://latteye.com/2011/11/15-minutes-introduction-to-redis-data-types.html#comments</comments>
		<pubDate>Thu, 24 Nov 2011 09:12:59 +0000</pubDate>
		<dc:creator>latteye</dc:creator>
				<category><![CDATA[Work / 努力工作]]></category>
		<category><![CDATA[redis]]></category>

		<guid isPermaLink="false">http://latteye.com/?p=1323</guid>
		<description><![CDATA[本文转载自 1001i blog。 你也许已经知道Redis并不是简单的 key-value 存储，实际上他是一个数据结构服务器，支持不同类型的值。也就是说，你不必仅仅把字符串当作键所指向的值。下列这些数据类型都可作为值类型。 二进制安全的 字符串 string 二进制安全的 字符串列表 list of string 二进制安全的 字符串集合 set of string，换言之：它是一组无重复未排序的element。可以把它看成Ruby中的 hash–其key等于element，value 都等于‘true’。 有序集合sorted set of string，类似于集合set，但其中每个元素都和一个浮点数score（评分）关联。element根据score排序。可以把它看成Ruby中的 hash–其key等于element，value等于score，但元素总是按score的顺序排列，无需额外的排序操作。 Redis 键 Redis key值是二进制安全的，这意味着可以用任何二进制序列作为key值，从形如”foo”的简单字符串到一个JPEG文件的内容都可以。空字符串也是有效key值。 关于key的几条规则： 太长的键值不是个好主意，例如1024字节的键值就不是个好主意，不仅因为消耗内存，而且在数据中查找这类键值的计算成本很高。 太短的键值通常也不是好主意，如果你要用”u:1000:pwd”来代替”user:1000:password”，这没有什么问题，但后者更易阅读，并且由此增加的空间消耗相对于key object和value object本身来说很小。当然，没人阻止您一定要用更短的键值节省一丁点儿空间。 最好坚持一种模式。例如：”object-type:id:field”就是个不错的注意，像这样”user:1000:password”。我喜欢对多单词的字段名中加上一个点，就像这样：”comment:1234:reply.to”。 字符串类型 这是最简单Redis类型。如果你只用这种类型，Redis就像一个可以持久化的memcached服务器（注：memcache的数据仅保存在内存中，服务器重启后，数据将丢失）。 我们来玩儿一下字符串类型： $ redis-cli set mykey "my binary safe value" OK $ redis-cli get mykey my binary safe [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>本文转载自 <a href="http://blog.1001i.com/databases/redis/introduce-redis" title="1001i blog" target="_blank">1001i blog</a>。<span id="more-1323"></span><br />
你也许已经知道Redis并不是简单的 key-value 存储，实际上他是一个数据结构服务器，支持不同类型的值。也就是说，你不必仅仅把字符串当作键所指向的值。下列这些数据类型都可作为值类型。</p>
<ul>
<li>二进制安全的 字符串 string</li>
<li>二进制安全的 字符串列表 list of string</li>
<li>二进制安全的 字符串集合 set of string，换言之：它是一组无重复未排序的element。可以把它看成Ruby中的 hash–其key等于element，value 都等于‘true’。</li>
<li>有序集合sorted set of string，类似于集合set，但其中每个元素都和一个浮点数score（评分）关联。element根据score排序。可以把它看成Ruby中的 hash–其key等于element，value等于score，但元素总是按score的顺序排列，无需额外的排序操作。</li>
</ul>
<p><strong>Redis 键</strong></p>
<p>Redis key值是二进制安全的，这意味着可以用任何二进制序列作为key值，从形如”foo”的简单字符串到一个JPEG文件的内容都可以。空字符串也是有效key值。</p>
<p>关于key的几条规则：</p>
<ul>
<li>太长的键值不是个好主意，例如1024字节的键值就不是个好主意，不仅因为消耗内存，而且在数据中查找这类键值的计算成本很高。</li>
<li>太短的键值通常也不是好主意，如果你要用”u:1000:pwd”来代替”user:1000:password”，这没有什么问题，但后者更易阅读，并且由此增加的空间消耗相对于key object和value object本身来说很小。当然，没人阻止您一定要用更短的键值节省一丁点儿空间。</li>
<li>最好坚持一种模式。例如：”object-type:id:field”就是个不错的注意，像这样”user:1000:password”。我喜欢对多单词的字段名中加上一个点，就像这样：”comment:1234:reply.to”。</li>
</ul>
<p><strong>字符串类型</strong></p>
<p>这是最简单Redis类型。如果你只用这种类型，Redis就像一个可以持久化的memcached服务器（注：memcache的数据仅保存在内存中，服务器重启后，数据将丢失）。<br />
我们来玩儿一下字符串类型：</p>
<p><code>$ redis-cli set mykey "my binary safe value"<br />
OK<br />
$ redis-cli get mykey<br />
my binary safe value</code></p>
<p>正如你所见到的，通常用SET command 和 GET command来设置和获取字符串值。<br />
值可以是任何种类的字符串（包括二进制数据），例如你可以在一个键下保存一副jpeg图片。值的长度不能超过1GB。<br />
虽然字符串是Redis的基本值类型，但你仍然能通过它完成一些有趣的操作。例如：原子递增：</p>
<p><code>$ redis-cli set counter 100<br />
OK $ redis-cli incr counter<br />
(integer) 101<br />
$ redis-cli incr counter<br />
(integer) 102<br />
$ redis-cli incrby counter 10<br />
(integer) 112</code></p>
<p><a href="http://blog.1001i.com/databases/redis-command/strings/incr" title="INCR Command" target="_blank">INCR</a> 命令将字符串值解析成整型，将其加一，最后将结果保存为新的字符串值，类似的命令有<a href="http://blog.1001i.com/databases/redis-command/strings/incrby" title="INCRBY Command" target="_blank">INCRBY</a>, <a href="http://blog.1001i.com/databases/redis-command/strings/decr" title="DCER Command" target="_blank">DECR</a> and <a href="http://blog.1001i.com/databases/redis-command/strings/decrby" title="DCERBY Command" target="_blank">DECRBY</a>。实际上他们在内部就是同一个命令，只是看上去有点儿不同。</p>
<p>INCR是原子操作意味着什么呢？就是说即使多个客户端对同一个key发出INCR命令，也决不会导致竞争的情况。例如如下情况永远不可能发生：『客户端1和客户端2同时读出“10”，他们俩都对其加到11，然后将新值设置为11』。最终的值一定是12，read-increment-set操作完成时，其他客户端不会在同一时间执行任何命令。</p>
<p>对字符串，另一个的令人感兴趣的操作是<a href="http://blog.1001i.com/databases/redis-command/strings/getset" title="GETSET Command" target="_blank">GETSET</a>命令，行如其名：他为key设置新值并且返回原值。这有什么用处呢？例如：你的系统每当有新用户访问时就用INCR命令操作一个Redis key。你希望每小时对这个信息收集一次。你就可以GETSET这个key并给其赋值0并读取原值。</p>
<p><strong>列表类型</strong></p>
<p>要说清楚列表数据类型，最好先讲一点儿理论背景，在信息技术界List这个词常常被使用不当。例如”Python Lists”就名不副实（名为Linked Lists），但他们实际上是数组（同样的数据类型在Ruby中叫数组）</p>
<p>一般意义上讲，列表就是有序元素的序列：10,20,1,2,3就是一个列表。但用数组实现的List和用Linked List实现的List，在属性方面大不相同。</p>
<p>Redis lists基于Linked Lists实现。这意味着即使在一个list中有数百万个元素，在头部或尾部添加一个元素的操作，其时间复杂度也是常数级别的。用 <a href="http://redis.io/commands/lpush" title="LPUSH Command" target="_blank">LPUSH</a> 命令在十个元素的list头部添加新元素，和在千万元素list头部添加新元素的速度相同。</p>
<p>那么，坏消息是什么？在数组实现的list中利用索引访问元素的速度极快，而同样的操作在linked list实现的list上没有那么快。</p>
<blockquote><p>Redis Lists are implemented with linked lists because for a database system it is crucial to be able to add elements to a very long list in a very fast way. Another strong advantage is, as you’ll see in a moment, that Redis Lists can be taken at constant length in constant time.</p></blockquote>
<p>Redis Lists用linked list实现的原因是：对于数据库系统来说，至关重要的特性是：能非常快的在很大的列表上添加元素。另一个重要因素是，正如你将要看到的：Redis lists能在常数时间取得常数长度。</p>
<p><strong>Redis lists 入门</strong></p>
<p>LPUSH 命令可向list的左边（头部）添加一个新元素，而RPUSH命令可向list的右边（尾部）添加一个新元素。最后LRANGE 命令可从list中取出一定范围的元素</p>
<p><code>$ redis-cli rpush messages "Hello how are you?"<br />
OK<br />
$ redis-cli rpush messages "Fine thanks. I‘m having fun with Redis"<br />
OK<br />
$ redis-cli rpush messages "I should look into this NOSQL thing ASAP"<br />
OK<br />
$ redis-cli lrange messages 0 2<br />
1. Hello how are you?<br />
2. Fine thanks. I‘m having fun with Redis<br />
3. I should look into this NOSQL thing ASAP</code></p>
<p>注意LRANGE 带有两个索引，一定范围的第一个和最后一个元素。这两个索引都可以为负来告知Redis从尾部开始计数，因此-1表示最后一个元素，-2表示list中的倒数第二个元素，以此类推。</p>
<blockquote><p>As you can guess from the example above, lists can be used, for instance, in order to implement a chat system. Another use is as queues in order to route messages between different processes. But the key point is that you can use Redis lists every time you require to access data in the same order they are added. This will not require any SQL ORDER BY operation, will be very fast, and will scale to millions of elements even with a toy Linux box.</p></blockquote>
<p>正如你可以从上面的例子中猜到的，list可被用来实现聊天系统。还可以作为不同进程间传递消息的队列。关键是，你可以每次都以原先添加的顺序访问数据。这不需要任何SQL ORDER BY 操作，将会非常快，也会很容易扩展到百万级别元素的规模。</p>
<p>例如在评级系统中，比如社会化新闻网站 reddit.com，你可以把每个新提交的链接添加到一个list，用LRANGE可简单的对结果分页。</p>
<p>在博客引擎实现中，你可为每篇日志设置一个list，在该list中推入进博客评论，等等。</p>
<p><strong>向Redis list压入ID而不是实际的数据</strong></p>
<p>在上面的例子里 ，我们将“对象”（此例中是简单消息）直接压入Redis list，但通常不应这么做，由于对象可能被多次引用：例如在一个list中维护其时间顺序，在一个集合中保存它的类别，只要有必要，它还会出现在其他list中，等等。</p>
<p>让我们回到reddit.com的例子，将用户提交的链接（新闻）添加到list中，有更可靠的方法如下所示：</p>
<p><code>$ redis-cli incr next.news.id<br />
(integer) 1<br />
$ redis-cli set news:1:title "Redis is simple"<br />
OK<br />
$ redis-cli set news:1:url "http://code.google.com/p/redis"<br />
OK<br />
$ redis-cli lpush submitted.news 1<br />
OK</code></p>
<p>我们自增一个key，很容易得到一个独一无二的自增ID，然后通过此ID创建对象–为对象的每个字段设置一个key。最后将新对象的ID压入submitted.news list。</p>
<p>这只是牛刀小试。在<a href="http://redis.io/commands" target="_blank">命令参考文档</a>中可以读到所有和list有关的命令。你可以删除元素，旋转list，根据索引获取和设置元素，当然也可以用LLEN得到list的长度。</p>
<p><strong>Redis 集合</strong></p>
<p>Redis集合是未排序的集合，其元素是二进制安全的字符串。SADD命令可以向集合添加一个新元素。和sets相关的操作也有许多，比如检测某个元素是否存在，以及实现交集，并集，差集等等。一例胜千言：</p>
<p><code>$ redis-cli sadd myset 1<br />
(integer) 1<br />
$ redis-cli sadd myset 2<br />
(integer) 1<br />
$ redis-cli sadd myset 3<br />
(integer) 1<br />
$ redis-cli smembers myset<br />
1. 3<br />
2. 1<br />
3. 2</code></p>
<p>我向集合中添加了三个元素，并让Redis返回所有元素。如你所见它们是无序的。</p>
<p>现在让我们检查某个元素是否存在：</p>
<p><code>$ redis-cli sismember myset 3<br />
(integer) 1<br />
$ redis-cli sismember myset 30<br />
(integer) 0</code></p>
<p>“3″是这个集合的成员，而“30”不是。集合特别适合表现对象之间的关系。例如用Redis集合可以很容易实现标签功能。</p>
<p>下面是一个简单的方案：对每个想加标签的对象，用一个标签ID集合与之关联，并且对每个已有的标签，一组对象ID与之关联。</p>
<p>例如假设我们的新闻ID 1000被加了三个标签tag 1,2,5和77，就可以设置下面两个集合：</p>
<p><code>$ redis-cli sadd news:1000:tags 1<br />
(integer) 1<br />
$ redis-cli sadd news:1000:tags 2<br />
(integer) 1<br />
$ redis-cli sadd news:1000:tags 5<br />
(integer) 1<br />
$ redis-cli sadd news:1000:tags 77<br />
(integer) 1<br />
$ redis-cli sadd tag:1:objects 1000<br />
(integer) 1<br />
$ redis-cli sadd tag:2:objects 1000<br />
(integer) 1<br />
$ redis-cli sadd tag:5:objects 1000<br />
(integer) 1<br />
$ redis-cli sadd tag:77:objects 1000<br />
(integer) 1</code></p>
<p>要获取一个对象的所有标签，如此简单：</p>
<p><code>$ redis-cli smembers news:1000:tags<br />
1. 5<br />
2. 1<br />
3. 77<br />
4. 2</code></p>
<p>而有些看上去并不简单的操作仍然能使用相应的Redis命令轻松实现。例如我们也许想获得一份同时拥有标签1, 2, 10和27的对象列表。这可以用SINTER命令来做，他可以在不同集合之间取出交集。因此为达目的我们只需：</p>
<p><code>$ redis-cli sinter tag:1:objects tag:2:objects tag:10:objects tag:27:objects<br />
... no result in our dataset composed of just one object <img src='http://latteye.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ...</code></p>
<p>在命令参考文档中可以找到和集合相关的其他命令，令人感兴趣的一抓一大把。一定要留意SORT命令，Redis集合和list都是可排序的。</p>
<p><strong>题外话：如何为字符串获取唯一标识</strong></p>
<p>在标签的例子里，我们用到了标签ID，却没有提到ID从何而来。基本上你得为每个加入系统的标签分配一个唯一标识。你也希望在多个客户端同时试着添加同样的标签时不要出现竞争的情况。此外，如果标签已存在，你希望返回他的ID，否则创建一个新的唯一标识并将其与此标签关联。</p>
<p>Redis 1.4将增加Hash类型。有了它，字符串和唯一ID关联的事儿将不值一提，但如今我们如何用现有Redis命令可靠的解决它呢？</p>
<p>我们首先的尝试（以失败告终）可能如下。假设想为标签“redis”获取一个唯一ID：</p>
<ul>
<li>为了让算法是二进制安全的（意即不考虑字符串的编码或空格等等，只将注意力放在标签上）我们对标签做SHA1签名。SHA1(redis)=b840fc02d524045429941cc15f59e41cb7be6c52。</li>
<li>检查这个标签是否已与一个唯一ID关联，用命令GET tag:b840fc02d524045429941cc15f59e41cb7be6c52:id</li>
<li>如果上面的GET操作返回一个ID，则将其返回给用户。标签已经存在了。</li>
<li>否则… 用INCR next.tag.id命令生成一个新的唯一ID（假定它返回123456）。</li>
<li>最后关联标签和新的ID，SET tag:b840fc02d524045429941cc15f59e41cb7be6c52:id 123456</li>
<li>并将新ID返回给调用者。</li>
</ul>
<p>多美妙，或许更好…等等！当两个客户端同时使用这组指令尝试为标签“redis”获取唯一ID时会发生什么呢？如果时间凑巧，他们俩都会从GET操作获得nil，都将对next.tag.id key做自增操作，这个key会被自增两次。其中一个客户端会将错误的ID返回给调用者。幸运的是修复这个算法并不难，这是明智的版本：</p>
<ul>
<li>为了让算法是二进制安全的（意即不考虑字符串的编码或空格等等，只将注意力放在标签上）我们对标签做SHA1签名。SHA1(redis)=b840fc02d524045429941cc15f59e41cb7be6c52。</li>
<li>检查这个标签是否已与一个唯一ID关联，用命令GET tag:b840fc02d524045429941cc15f59e41cb7be6c52:id</li>
<li>如果上面的GET操作返回一个ID，则将其返回给用户。标签已经存在了。</li>
<li>否则… 用INCR next.tag.id命令生成一个新的唯一ID（假定它返回123456）。</li>
<li>下面关联标签和新的ID，(注意用到一个新的命令)</li>
<p>SETNX tag:b840fc02d524045429941cc15f59e41cb7be6c52:id 123456。如果另一个客户端比当前客户端更快，SETNX将不会设置key。而且，当key被成功设置时SETNX返回1，否则返回0。那么…让我们再做最后一步运算。</li>
<li>如果SETNX返回1（key设置成功）则将123456返回给调用者，这就是我们的标签ID，否则执行GET tag:b840fc02d524045429941cc15f59e41cb7be6c52:id 并将其结果返回给调用者。</li>
</ul>
<p><strong>有序集合</strong></p>
<p>集合是使用频率很高的数据类型，但是…对许多问题来说他们也有点儿太不讲顺序了;)因此Redis1.2引入了有序集合。他和集合非常相似，也是二进制安全的字符串集合，但是这次带有关联的score，以及一个类似LRANGE的操作可以返回有序元素，此操作只能作用于有序集合，它就是，ZRANGE 命令。</p>
<p>从某种程度上说，有序集合是SQL世界的索引在Redis中的等价物。例如在刚才的reddit.com例子中，并没有提到如何根据用户投票和时间因素将新闻组合生成首页。下面我们会用有序集合解决这个问题，我们先从最简单的事情开始，阐明这个高级数据类型是如何工作的。让我们添加几个黑客，并将他们的生日作为“score”。</p>
<p><code>$ redis-cli zadd hackers 1940 "Alan Kay"<br />
(integer) 1<br />
$ redis-cli zadd hackers 1953 "Richard Stallman"<br />
(integer) 1<br />
$ redis-cli zadd hackers 1965 "Yukihiro Matsumoto"<br />
(integer) 1<br />
$ redis-cli zadd hackers 1916 "Claude Shannon"<br />
(integer) 1<br />
$ redis-cli zadd hackers 1969 "Linus Torvalds"<br />
(integer) 1<br />
$ redis-cli zadd hackers 1912 "Alan Turing"<br />
(integer) 1</code></p>
<p>对有序集合来说，按生日排序返回这些黑客易如反掌，因为他们已经是有序的。有序集合是通过一个dual-ported 数据结构实现的，它包含一个精简的有序列表和一个hash table，因此添加一个元素的时间复杂度是O(log(N))。这还行，但当我们需要访问有序的元素时，Redis不必再做任何事情，它已经是有序的了：</p>
<p><code>$ redis-cli zrange hackers 0 -1<br />
1. Alan Turing<br />
2. Claude Shannon<br />
3. Alan Kay<br />
4. Richard Stallman<br />
5. Yukihiro Matsumoto<br />
6. Linus Torvalds</code></p>
<p>你知道Linus比Yukihiro年轻吗 <img src='http://latteye.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>无论如何，我想反向对这些元素排序，这次就用 ZREVRANGE 代替 ZRANGE 吧：</p>
<p><code>$ redis-cli zrevrange hackers 0 -1<br />
1. Linus Torvalds<br />
2. Yukihiro Matsumoto<br />
3. Richard Stallman<br />
4. Alan Kay<br />
5. Claude Shannon<br />
6. Alan Turing</code></p>
<p>一个非常重要的小贴士，ZSets只是有一个“默认的”顺序，但你仍然可以用 SORT 命令对有序集合做不同的排序（但这次服务器要耗费CPU了）。要想得到多种排序，一种可选方案是同时将每个元素加入多个有序集合。</p>
<p><strong>区间操作</strong></p>
<p>有序集合之能不止于此，他能在区间上操作。例如获取所有1950年之前出生的人。我们用 ZRANGEBYSCORE 命令来做：</p>
<p><code>$ redis-cli zrangebyscore hackers -inf 1950<br />
1. Alan Turing<br />
2. Claude Shannon<br />
3. Alan Kay</code></p>
<p>我们请求Redis返回score介于负无穷到1950年之间的元素（两个极值也包含了）。</p>
<p>也可以删除区间内的元素。例如从有序集合中删除生日介于1940到1960年之间的黑客。</p>
<p><a href="http://redis.io/commands/zremrangebyscore" target="_blank">ZREMRANGEBYSCORE</a> 这个名字虽然不算好，但他却非常有用，还会返回已删除的元素数量。</p>
<p><strong>回到Reddit的例子</strong></p>
<p>最后，回到 Reddit的例子。现在我们有个基于有序集合的像样方案来生成首页。用一个有序集合来包含最近几天的新闻（用 ZREMRANGEBYSCORE 不时的删除旧新闻）。用一个后台任务从有序集合中获取所有元素，根据用户投票和新闻时间计算score，然后用新闻IDs和scores关联生成 reddit.home.page 有序集合。要显示首页，我们只需闪电般的调用 ZRANGE。</p>
<p>不时的从 reddit.home.page 有序集合中删除过旧的新闻也是为了让我们的系统总是工作在有限的新闻集合之上。</p>
<p><strong>更新有序集合的scores</strong></p>
<p>结束这篇指南之前还有最后一个小贴士。有序集合scores可以在任何时候更新。只要用 ZADD 对有序集合内的元素操作就会更新它的score（和位置），时间复杂度是O(log(N))，因此即使大量更新，有序集合也是合适的。</p>
<p>这篇指南远未尽言，这只是从Redis开始的基础，欲深入之请读命令参考文档。</p>
<p>谢谢阅读。Salvatore。</p>
<p>本文整理在 <a href="http://latteye.com/doc" title="文档" target="_blank">latteye doc 页面</a></p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://latteye.com/2011/11/15-minutes-introduction-to-redis-data-types.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>说说键盘吧</title>
		<link>http://latteye.com/2011/11/keyboard.html</link>
		<comments>http://latteye.com/2011/11/keyboard.html#comments</comments>
		<pubDate>Wed, 23 Nov 2011 16:31:22 +0000</pubDate>
		<dc:creator>latteye</dc:creator>
				<category><![CDATA[Life ㄆ 自己生活]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[dell]]></category>
		<category><![CDATA[g5]]></category>
		<category><![CDATA[g6]]></category>
		<category><![CDATA[keyboard]]></category>

		<guid isPermaLink="false">http://latteye.com/?p=1321</guid>
		<description><![CDATA[今天收到了 Apple G5 键盘，虽然满怀期待，但又有诸多不爽。 刚用电脑的时候其实对键盘不是特别在意。自从千年特意买了个 Dell 8175 键盘之后（上图那黑黑的一块，呵呵），对键盘也算有点小要求。8175 的确是个好键盘，适中的键程，柔软的触感，恰到好处的反弹，让人一上手就有一种肉乎乎的感觉。 Macbook Air 自带的键盘其实还是不错的，我不是很喜欢这种巧克力键盘，总觉得他拉大了键距。但是 MBA 的巧克力键盘没有给我任何不爽的感觉，也没花多少时间去适应他。 由于要将笔记本连接到外置显示器使用，所以一个外置 Apple 键盘就成了必备配件。 可惜的是 Apple 并没有给你太多的选择，由于特有的 Command 按键，你必须使用 Apple 自家的键盘。先上手的是 G6 有线键盘。 这款键盘的排列其实和笔记本还是略有不同的。手感上相差了很多，最大的区别是硬，一天用下来我的手指好想有点痛的感觉，悲催～ 其实各人使用习惯不一，我按键比较用力，所以键程短的键盘肯定不适合我。容易让我觉得痛。外加这块键盘硬…… 在用了1个月不到，感觉空格键也有点小问题之后今天果断入 G5 键盘。 其实就外观而言，我更喜欢G5.这种油乎乎肥嘟嘟的感觉让人心情愉悦。 但是今天一天用下来，体验并不是很好，我不知道我买的这个是不是真的，这是另外的话题了～ 首先，键程比 Dell 的 8175 要长，我觉得过长了。于是小几率的，我会按不到某个键。另外键距比 Apple G6 要宽，使用起来感觉有点累。同时由于键宽和造型的不一，盲打的时候命中率比平时略低了一点。可能需要一点时间适应吧。 G5 的造型的确是花了心思的，这种弯曲的造型能让你在按上面几排按键的时候，手指要伸出的距离略短。但其实上面几排去按的几率还是比较小的。 另外，其实我很喜欢 G6 无线版本的按键排布，主要是键盘短了。我根本不需要小键盘，F14 F15 这种按键，Home键我也几乎不用。而键盘短了以后右手伸出去握鼠标的舒适度大大增加。 真希望G5能出一个改进版本。 No related posts.
No related posts.]]></description>
			<content:encoded><![CDATA[<p>今天收到了 Apple G5 键盘，虽然满怀期待，但又有诸多不爽。<span id="more-1321"></span></p>
<p><img src="http://pic.yupoo.com/latteye/Bxzf7imf/medish.jpg" alt="keyboard" /></p>
<p>刚用电脑的时候其实对键盘不是特别在意。自从千年特意买了个 Dell 8175 键盘之后（上图那黑黑的一块，呵呵），对键盘也算有点小要求。8175 的确是个好键盘，适中的键程，柔软的触感，恰到好处的反弹，让人一上手就有一种肉乎乎的感觉。</p>
<p>Macbook Air 自带的键盘其实还是不错的，我不是很喜欢这种巧克力键盘，总觉得他拉大了键距。但是 MBA 的巧克力键盘没有给我任何不爽的感觉，也没花多少时间去适应他。</p>
<p>由于要将笔记本连接到外置显示器使用，所以一个外置 Apple 键盘就成了必备配件。<br />
可惜的是 Apple 并没有给你太多的选择，由于特有的 Command 按键，你必须使用 Apple 自家的键盘。先上手的是 G6 有线键盘。</p>
<p><img src="http://pic.yupoo.com/latteye/Bxzfdnhb/medish.jpg" alt="Apple G6" /></p>
<p>这款键盘的排列其实和笔记本还是略有不同的。手感上相差了很多，最大的区别是硬，一天用下来我的手指好想有点痛的感觉，悲催～<br />
其实各人使用习惯不一，我按键比较用力，所以键程短的键盘肯定不适合我。容易让我觉得痛。外加这块键盘硬……</p>
<p>在用了1个月不到，感觉空格键也有点小问题之后今天果断入 G5 键盘。</p>
<p><img src="http://pic.yupoo.com/latteye/Bxzfj0K0/medish.jpg" alt="Apple G5" /></p>
<p>其实就外观而言，我更喜欢G5.这种油乎乎肥嘟嘟的感觉让人心情愉悦。<br />
但是今天一天用下来，体验并不是很好，我不知道我买的这个是不是真的，这是另外的话题了～</p>
<p>首先，键程比 Dell 的 8175 要长，我觉得过长了。于是小几率的，我会按不到某个键。另外键距比 Apple G6 要宽，使用起来感觉有点累。同时由于键宽和造型的不一，盲打的时候命中率比平时略低了一点。可能需要一点时间适应吧。<br />
G5 的造型的确是花了心思的，这种弯曲的造型能让你在按上面几排按键的时候，手指要伸出的距离略短。但其实上面几排去按的几率还是比较小的。<br />
另外，其实我很喜欢 G6 无线版本的按键排布，主要是键盘短了。我根本不需要小键盘，F14 F15 这种按键，Home键我也几乎不用。而键盘短了以后右手伸出去握鼠标的舒适度大大增加。</p>
<p>真希望G5能出一个改进版本。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://latteye.com/2011/11/keyboard.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RedHat&amp;CentOS&amp;Amazon Linux 6 httpd mod_proxy_balancer bug</title>
		<link>http://latteye.com/2011/11/redhatcentosamazon-linux-6-httpd-mod_proxy_balancer-bug.html</link>
		<comments>http://latteye.com/2011/11/redhatcentosamazon-linux-6-httpd-mod_proxy_balancer-bug.html#comments</comments>
		<pubDate>Sat, 19 Nov 2011 14:16:16 +0000</pubDate>
		<dc:creator>latteye</dc:creator>
				<category><![CDATA[Work / 努力工作]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[balancer]]></category>
		<category><![CDATA[httpd]]></category>
		<category><![CDATA[tomcat]]></category>

		<guid isPermaLink="false">http://latteye.com/?p=1318</guid>
		<description><![CDATA[在 Amazon Linux 上应用 Apache httpd mod_proxy_balancer 模块，后端 tomcat 需要 session，于是使用到了 stickysession 功能，但起初无论如何都无法令其工作。于是再转入 CentOS 6 环境测试，发现效果一样。 不工作的配置： &#60;VirtualHost *:80&#62; ProxyPass / balancer://appCluster/ stickysession=JSESSIONID ProxyPassReverse / balancer://appCluster/ &#60;/VirtualHost&#62; &#160; &#60;Proxy balancer://appCluster&#62; BalancerMember ajp://172.16.5.154:8009 smax=5 route=jvm1 retry=60 ttl=60 BalancerMember ajp://172.16.5.154:8010 smax=5 route=jvm2 retry=60 ttl=60 &#60;/Proxy&#62; 工作的配置： &#60;VirtualHost *:80&#62; ProxyPass / balancer://appCluster/ ProxyPassReverse / balancer://appCluster/ &#60;/VirtualHost&#62; &#160; &#60;Proxy [...]
Related posts:<ol>
<li><a href='http://latteye.com/2011/10/mongodb-note-1.html' rel='bookmark' title='MongoDB 笔记 1'>MongoDB 笔记 1</a></li>
<li><a href='http://latteye.com/2007/09/add-linux-to-windows-domain-with-winbind.html' rel='bookmark' title='使用 Winbind 将 Linux 加入 Windows 域环境'>使用 Winbind 将 Linux 加入 Windows 域环境</a></li>
<li><a href='http://latteye.com/2010/09/%e5%8f%91%e5%b8%83%e4%b8%80%e4%b8%aa-a-p-i.html' rel='bookmark' title='发布一个 A.P.I'>发布一个 A.P.I</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>在 Amazon Linux 上应用 Apache httpd mod_proxy_balancer 模块，后端 tomcat 需要 session，于是使用到了 stickysession 功能，但起初无论如何都无法令其工作。于是再转入 CentOS 6 环境测试，发现效果一样。<span id="more-1318"></span></p>
<p>不工作的配置：</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"> &lt;<span style="color: #000000; font-weight:bold;">VirtualHost</span> *:<span style="color: #ff0000;">80</span>&gt;
     <span style="color: #00007f;">ProxyPass</span> / balancer://appCluster/ stickysession=JSESSIONID
     <span style="color: #00007f;">ProxyPassReverse</span> / balancer://appCluster/
 &lt;/<span style="color: #000000; font-weight:bold;">VirtualHost</span>&gt;
&nbsp;
 &lt;<span style="color: #000000; font-weight:bold;">Proxy</span> balancer://appCluster&gt;
     <span style="color: #00007f;">BalancerMember</span> ajp://172.16.5.154:<span style="color: #ff0000;">8009</span> smax=<span style="color: #ff0000;">5</span> route=jvm1 retry=<span style="color: #ff0000;">60</span> ttl=<span style="color: #ff0000;">60</span>
     <span style="color: #00007f;">BalancerMember</span> ajp://172.16.5.154:<span style="color: #ff0000;">8010</span> smax=<span style="color: #ff0000;">5</span> route=jvm2 retry=<span style="color: #ff0000;">60</span> ttl=<span style="color: #ff0000;">60</span>
 &lt;/<span style="color: #000000; font-weight:bold;">Proxy</span>&gt;</pre></div></div>

<p>工作的配置：</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">VirtualHost</span> *:<span style="color: #ff0000;">80</span>&gt;
	<span style="color: #00007f;">ProxyPass</span> / balancer://appCluster/
	<span style="color: #00007f;">ProxyPassReverse</span> / balancer://appCluster/
&lt;/<span style="color: #000000; font-weight:bold;">VirtualHost</span>&gt;
&nbsp;
&lt;<span style="color: #000000; font-weight:bold;">Proxy</span> balancer://appCluster&gt;
    <span style="color: #00007f;">BalancerMember</span> ajp://172.16.5.154:<span style="color: #ff0000;">8009</span> smax=<span style="color: #ff0000;">5</span> route=jvm1 retry=<span style="color: #ff0000;">60</span> ttl=<span style="color: #ff0000;">60</span>
    <span style="color: #00007f;">BalancerMember</span> ajp://172.16.5.154:<span style="color: #ff0000;">8010</span> smax=<span style="color: #ff0000;">5</span> route=jvm2 retry=<span style="color: #ff0000;">60</span> ttl=<span style="color: #ff0000;">60</span>
    <span style="color: #00007f;">ProxySet</span> stickysession=JSESSIONID
&lt;/<span style="color: #000000; font-weight:bold;">Proxy</span>&gt;</pre></div></div>

<p>按照 <a href="http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxyset" title="ProxySet" target="_blank">ProxySet</a> 的解释，它也只是到了后面的一种替代配置方式。而按照 <a href="http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass" title="ProxyPass" target="_blank">ProxyPass</a> 的说明，这两种配置方式都应该是工作的。于是我开始做跟进一步的跟踪。</p>
<p>配置 balancer log：</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #00007f;">LogFormat</span> <span style="color: #7f007f;">&quot;<span style="color: #000099; font-weight: bold;">\&quot;</span>%{MYCOOKIE}C<span style="color: #000099; font-weight: bold;">\&quot;</span> <span style="color: #000099; font-weight: bold;">\&quot;</span>%{Set-Cookie}o<span style="color: #000099; font-weight: bold;">\&quot;</span> <span style="color: #000099; font-weight: bold;">\&quot;</span>%{BALANCER_SESSION_STICKY}e<span style="color: #000099; font-weight: bold;">\&quot;</span> <span style="color: #000099; font-weight: bold;">\&quot;</span>%{BALANCER_SESSION_ROUTE}e<span style="color: #000099; font-weight: bold;">\&quot;</span> <span style="color: #000099; font-weight: bold;">\&quot;</span>%{BALANCER_WORKER_ROUTE}e<span style="color: #000099; font-weight: bold;">\&quot;</span> <span style="color: #000099; font-weight: bold;">\&quot;</span>%{BALANCER_ROUTE_CHANGED}e<span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span> session
<span style="color: #00007f;">CustomLog</span> logs/session_log session</pre></div></div>

<p>工作的 log：</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;jvm1&quot;</span> <span style="color: #7f007f;">&quot;1&quot;</span>
<span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;1&quot;</span>
<span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;jvm1&quot;</span> <span style="color: #7f007f;">&quot;1&quot;</span>
<span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;JSESSIONID=8B23E43DC6CA0C11BFB14A7D40A3C489.jvm2; Path=/ewallet/; HttpOnly&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;1&quot;</span>
<span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;JSESSIONID&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span>
<span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;JSESSIONID&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span>
<span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;JSESSIONID&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span>
<span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;JSESSIONID&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span></pre></div></div>

<p>不工作的 log：</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;JSESSIONID=8277BFA34D8B787722F39251F223A837.jvm1; Path=/ewallet/; HttpOnly&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;jvm1&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span>
<span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span>
<span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;jvm1&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span>
<span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span> <span style="color: #7f007f;">&quot;jvm2&quot;</span> <span style="color: #7f007f;">&quot;-&quot;</span></pre></div></div>

<p>给我的感觉是 balancer 模块完全没有意识到需要按照 sessionid 的方式去选择 route。很明显 balancer 模块已经看到 cookie 了。</p>
<p>全局打开 debug 模式，工作的log：</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">mod_proxy_balancer.c(<span style="color: #ff0000;">46</span>): proxy: BALANCER: canonicalising URL //appCluster/ewallet/account
mod_proxy_balancer.c(<span style="color: #ff0000;">280</span>): proxy: BALANCER: Found value AAE5BBF643F75BFFE91FA4F7841B3847.jvm1 for stickysession JSESSIONID
mod_proxy_balancer.c(<span style="color: #ff0000;">290</span>): proxy: BALANCER: Found route jvm1
mod_proxy_balancer.c(<span style="color: #ff0000;">581</span>): proxy: BALANCER (balancer://appcluster) worker (ajp://172.16.5.154:<span style="color: #ff0000;">8009</span>) rewritten to ajp://172.16.5.154:<span style="color: #ff0000;">8009</span>/ewallet/account</pre></div></div>

<p>不工作的 log：</p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;">mod_proxy_balancer.c(<span style="color: #ff0000;">46</span>): proxy: BALANCER: canonicalising URL //appCluster/ewallet/login.jsp
 mod_proxy_balancer.c(<span style="color: #ff0000;">1003</span>): proxy: Entering byrequests for BALANCER (balancer://appcluster)
 mod_proxy_balancer.c(<span style="color: #ff0000;">1046</span>): proxy: byrequests selected worker <span style="color: #7f007f;">&quot;ajp://172.16.5.154:8009&quot;</span> : busy <span style="color: #ff0000;">0</span> : lbstatus <span style="color: #ff0000;">0</span>
 mod_proxy_balancer.c(<span style="color: #ff0000;">581</span>): proxy: BALANCER (balancer://appcluster) worker (ajp://172.16.5.154:<span style="color: #ff0000;">8009</span>) rewritten to ajp://172.16.5.154:<span style="color: #ff0000;">8009</span>/ewallet/login.jsp</pre></div></div>

<p>基本上可以确定为是一个 bug。然后我去 RedHat bugzilla 搜索了一下，看到一个类似的问题：<a href="https://bugzilla.redhat.com/show_bug.cgi?id=475787" target="_blank">mod_proxy_balancer: strange behaviour of multiple session identifiers [NEEDINFO]</a> 。不过原提交人未再给出详细的信息了。</p>
<p>Related posts:</p><ol>
<li><a href='http://latteye.com/2011/10/mongodb-note-1.html' rel='bookmark' title='MongoDB 笔记 1'>MongoDB 笔记 1</a></li>
<li><a href='http://latteye.com/2007/09/add-linux-to-windows-domain-with-winbind.html' rel='bookmark' title='使用 Winbind 将 Linux 加入 Windows 域环境'>使用 Winbind 将 Linux 加入 Windows 域环境</a></li>
<li><a href='http://latteye.com/2010/09/%e5%8f%91%e5%b8%83%e4%b8%80%e4%b8%aa-a-p-i.html' rel='bookmark' title='发布一个 A.P.I'>发布一个 A.P.I</a></li>
</ol>]]></content:encoded>
			<wfw:commentRss>http://latteye.com/2011/11/redhatcentosamazon-linux-6-httpd-mod_proxy_balancer-bug.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PC Low-Fi 之路 3</title>
		<link>http://latteye.com/2011/11/pc-low-fi-%e4%b9%8b%e8%b7%af-3.html</link>
		<comments>http://latteye.com/2011/11/pc-low-fi-%e4%b9%8b%e8%b7%af-3.html#comments</comments>
		<pubDate>Thu, 03 Nov 2011 14:41:00 +0000</pubDate>
		<dc:creator>latteye</dc:creator>
				<category><![CDATA[Life ㄆ 自己生活]]></category>
		<category><![CDATA[Music ∮ 听听音乐]]></category>
		<category><![CDATA[alsa]]></category>
		<category><![CDATA[archlinux]]></category>
		<category><![CDATA[homeserver]]></category>
		<category><![CDATA[mpd]]></category>
		<category><![CDATA[seas]]></category>

		<guid isPermaLink="false">http://latteye.com/?p=1312</guid>
		<description><![CDATA[在距离前两篇3个月之后[ 1 2 ]，我还是把 PC Low-Fi 之路完结一下吧，也算是阶段性完结器材折腾。 一、音箱 上篇说到 EL34 胆机。胆机之后自然就是音箱了。 起初我希望将音箱控制在 2000元 的价位。转了一圈以后发现这个价位是比较尴尬的。买国产音箱 2000 元好像有点浪费。虽然惠威这些年做的的确也蛮好，但是总觉得不值这个价格。但是买欧美箱子，2000 元够买个2手的。一开始看了 Roger 乐爵士的一些音箱。比较中意他的价位。网上谈了一些卖家，深圳那里的比较多，但总有点不放心。一来距离比较远，运输过程出了问题很难处理。而来对音箱真假没把握。后来也接触了一些上海的音箱代理商家，不过没什么深入了解。 8月那段时间，工作上处于比较轻松的阶段。突然想，既然要性价比高，不如自己做一个吧。于是开始逛音箱 DIY 论坛。发现 DIY 里面用西雅士单元的人很多。这个品牌的单元口碑非常好。技术工艺也已经发展到了金属盆，以前一直以为单元只能用纸盆做呢。 在淘宝上你可以看到很多的 DIY 音箱产品。炒的比较红的有款式叫中大4号。Google 了一下 Alesis 6.5 寸单元可能在 140 元的价位。通常高频单元不会比中低频贵，所以一套音箱基本成本大约在 600 以内。卖价 900 多也算是比较厚道了。而且我买 EL34 的小店也有推荐他们的音箱。 还是顺着西雅士的路线来看，找到了一个卖家自己 DIY 音箱的。同城，联系了一下，可以试听。找了一个晚上就跑去了。去之前还在犹豫是否要把自己一对先锋的组合音箱给带去做比较。去了之后庆幸幸好没带！带了就太废柴了！ 这款音箱彻底、完全、重新定义了我对音箱的看法（当然，以前也没听过 Hi-Fi，呵呵）。虽然 3200 略微有点超出预算，但还是感觉超值！ 西雅士 H1212+H1224 的组合非常普遍，很成熟的方案了。卖家的分频器好像是自己做的。试听的时候，我都开始不由自主的笑了！这才是音乐啊！声场、深度、力量、柔美完全结合在了一起。那种声音的包围感、水乳交融的感觉很难描绘出来。 卖家自己的系统模拟味很重，一开始听伊凡塞斯的Fallen 居然有点甜甜的感觉了。后来听 Yanni 的一张专辑，完全感觉不到数码的味道。（Yanni 的数码味那是相当的重啊！搞的和电子乐一样的感觉。） 乐呵呵的把音箱抱回家之后，果然有了很大的提升。应该不能用“提升”，应该说“颠覆”。这是完全不一样的声音。 [...]
No related posts.]]></description>
			<content:encoded><![CDATA[<p>在距离前两篇3个月之后[ <a href="http://latteye.com/2011/07/pc-low-fi-%e4%b9%8b%e8%b7%af-1.html" title="PC Low-Fi 之路 1" target="_blank">1</a> <a href="http://latteye.com/2011/07/pc-low-fi-%e4%b9%8b%e8%b7%af-2.html" title="PC Low-Fi 之路 2" target="_blank">2</a> ]，我还是把 PC Low-Fi 之路完结一下吧，也算是阶段性完结器材折腾。<span id="more-1312"></span></p>
<p><strong>一、音箱</strong><br />
上篇说到 EL34 胆机。胆机之后自然就是音箱了。<br />
起初我希望将音箱控制在 2000元 的价位。转了一圈以后发现这个价位是比较尴尬的。买国产音箱 2000 元好像有点浪费。虽然惠威这些年做的的确也蛮好，但是总觉得不值这个价格。但是买欧美箱子，2000 元够买个2手的。一开始看了 Roger 乐爵士的一些音箱。比较中意他的价位。网上谈了一些卖家，深圳那里的比较多，但总有点不放心。一来距离比较远，运输过程出了问题很难处理。而来对音箱真假没把握。后来也接触了一些上海的音箱代理商家，不过没什么深入了解。</p>
<p>8月那段时间，工作上处于比较轻松的阶段。突然想，既然要性价比高，不如自己做一个吧。于是开始逛音箱 DIY 论坛。发现 DIY 里面用<a href="http://www.seas.no/" title="SEAS" target="_blank">西雅士</a>单元的人很多。这个品牌的单元口碑非常好。技术工艺也已经发展到了金属盆，以前一直以为单元只能用纸盆做呢。<br />
在淘宝上你可以看到很多的 DIY 音箱产品。炒的比较红的有款式叫中大4号。Google 了一下 Alesis 6.5 寸单元可能在 140 元的价位。通常高频单元不会比中低频贵，所以一套音箱基本成本大约在 600 以内。卖价 900 多也算是比较厚道了。而且我买 EL34 的小店也有推荐他们的音箱。<br />
还是顺着西雅士的路线来看，找到了一个<a href="http://seas-sh.taobao.com/" target="_blank">卖家自己 DIY 音箱</a>的。同城，联系了一下，可以试听。找了一个晚上就跑去了。去之前还在犹豫是否要把自己一对先锋的组合音箱给带去做比较。去了之后庆幸幸好没带！带了就太废柴了！</p>
<p>这款音箱彻底、完全、重新定义了我对音箱的看法（当然，以前也没听过 Hi-Fi，呵呵）。虽然 3200 略微有点超出预算，但还是感觉超值！</p>
<p><img src="http://pic.yupoo.com/latteye/Buvs2Ugk/medish.jpg" alt="" /><br />
<img src="http://pic.yupoo.com/latteye/BuvJD9x6/medish.jpg" alt="" /></p>
<p>西雅士 H1212+H1224 的组合非常普遍，很成熟的方案了。卖家的分频器好像是自己做的。试听的时候，我都开始不由自主的笑了！这才是音乐啊！声场、深度、力量、柔美完全结合在了一起。那种声音的包围感、水乳交融的感觉很难描绘出来。<br />
卖家自己的系统模拟味很重，一开始听伊凡塞斯的Fallen 居然有点甜甜的感觉了。后来听 Yanni 的一张专辑，完全感觉不到数码的味道。（Yanni 的数码味那是相当的重啊！搞的和电子乐一样的感觉。）</p>
<p>乐呵呵的把音箱抱回家之后，果然有了很大的提升。应该不能用“提升”，应该说“颠覆”。这是完全不一样的声音。</p>
<p>不过，由于之前在卖家那里听了好的器材了（卖家说他的解码器就要 2w，我才花了 400块钱买解码器，差距是肯定有的啦⋯⋯），利马就能感觉到自己系统声音的缺陷。密度差了2个档次，声音有些松散。于是又开始折腾了。</p>
<p><strong>二、胆管</strong><br />
胆管可能是整套系统里面投资最不值得的一部分了。并不是说它没效果，而是性价比不高。原来胆机配的是南京曙光的胆管，我对应的换了两种胆管：</p>
<p>JJ 蓝瓶 EL34<br />
<img src="http://pic.yupoo.com/latteye/BuvPafOP/medish.jpg" alt="" /><br />
话说这瓶子是很好看！蓝瓶的好喝的！</p>
<p>天梭 6SL7<br />
<img src="http://pic.yupoo.com/latteye/BuvPwNhb/medish.jpg" alt="" /></p>
<p>其中，6SL7 是用来将接收到的信号放大的。EL34 是用来推动音箱的。还有一个将电源整流的瓶子没有换，那个因素相对比较小。<br />
换了瓶子之后，还是有所提升的。密度感好一些。貌似仅此而已⋯⋯，而4个瓶子好像就要 500 元左右。</p>
<p>后来看过一个卖解码器的卖家说，整套系统里面，在预算有限的情况下，建议是两头重、中间轻。也就是花多点钱在解码（CD、DAC）和音箱上，而功放相对少花点。我现在也非常赞同这点。</p>
<p><strong>三、网罩</strong><br />
胆机的确是可以煮鸡蛋的。有个同事的小孩差点把手摸上去。所以我定做了一个网罩。</p>
<p><img src="http://pic.yupoo.com/latteye/Buvszk8K/medish.jpg" alt="" /></p>
<p>只能说做的马马虎虎、凑合凑合。我没给中评已经很够意思了⋯⋯ 不过价钱比在自己家门口做便宜了不少。</p>
<p><strong>四、运放</strong><br />
某天回头转回到解码器，发现之前买的解码器可以很轻松的换运放。一开始也不知道运放什么作用，后来知道原来运放是做解析的。<br />
咬了咬牙买了套 金封 627SM，这个运放我买了 100 元，很多人可能是 140元左右收入的。我也不知道我买的是真的还是假的。</p>
<p><img src="http://pic.yupoo.com/latteye/Buvsl2YO/medish.jpg" alt="" /></p>
<p>这是原配的 2604AP 的照片，这个运放大约是 15元。所以比较而言 627SM 真的是很昂贵了。</p>
<p><img src="http://pic.yupoo.com/latteye/Buvsr2Mt/medish.jpg" alt="" /></p>
<p>说说 627SM 的听后感吧。<br />
一入耳的感觉是明亮了，但是明亮不代表是好，因为很多信号放大如果直接导致某部分音量变大（高音居多），也会给人一时的这种感觉。所以这个运放大约认真听了1个小时才明确了性能。</p>
<p>低音：低音的改善很明显，比较而言 2604 听一些 Punk EMO 的时候，鼓声和贝斯声都是挤在一起的。而 627SM 把声音解析的非常到位，一来分开了层次，而来鼓声变的很有弹性，你能够感觉到鼓被敲下然后弹上来的过程。<br />
高音：高音的解析无敌了。我以前从来没感觉到阿桑的《寂寞在唱歌》是有齿音和唇音的，太牛了！<br />
声场：不止是低音的层次被分开，整体的声音声场都能拉开的。音乐变的有起伏、音乐性感觉很强。我之前一直不理解别人说的“动态”是什么意思，现在可能有一点点感觉了。</p>
<p>晚上老婆下班回来，听了一会热，立刻也能感觉到更好的变化。运放的投入还是很值的。</p>
<p><strong>四、音乐管理</strong><br />
由于要上 3T 硬盘，所以把 Homeserver 改成了 ArchLinux 系统。使用 mpd 来管理音乐文件，mpd 的优点是各个平台都有对应的 client 来控制。远程遥控很方便。<br />
切换过来能明显感觉到 linux mpd alsa 的声音更加实在一些。对比而言，foobar 的声音就像是加了味精一样。似乎 foobar 通过一些软件的方式让声音更加有声场。但是这种感觉并不好，听的时间一长，会很厌烦。这种虚拟出来的声场真的不太舒服。<br />
目前 mpd 工作的很好，软件作者也保持着很积极的态度在更新。我甚至连 alsa service 都没有装，由 mpd 自己控制 alsa 模块做 soft 音量控制。</p>
<p>OK，到这里 PC Low-Fi 的流水账就完结了。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://latteye.com/2011/11/pc-low-fi-%e4%b9%8b%e8%b7%af-3.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MongoDB Javascript Driver 测试</title>
		<link>http://latteye.com/2011/10/mongodb-javascript-driver.html</link>
		<comments>http://latteye.com/2011/10/mongodb-javascript-driver.html#comments</comments>
		<pubDate>Mon, 24 Oct 2011 13:12:10 +0000</pubDate>
		<dc:creator>latteye</dc:creator>
				<category><![CDATA[Work / 努力工作]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[Node.js]]></category>

		<guid isPermaLink="false">http://latteye.com/?p=1283</guid>
		<description><![CDATA[在对 node.js + MongoDB 做了一周不到的测试之后，我们决定放弃这对组合。放弃的原因有二： MongoDB 对数据的保障性不是我们所需要的。这不是 MongoDB 的错误，这是我们选择产品的错误。我觉得 MongoDB 其实就是放弃了这样的数据保障性才获得了更好的性能。所以才更适合类似 facebook twitter 对消息保障性要求不高，但是量大的应用。 Javascript 的 driver 略显不成熟。其实各类开发速度都很快，同时我对他们的熟悉程度还不够好。所以总的感觉现在还没到用的时候。 这里对第二点做个流水账式样的记录，在学习的过程中发现相关的英文和中文资料都比较缺乏。 我所测试到的 Driver 有： node-mongodb-native mongolian mongoose 这三个 Driver 里，mongolian 和 mongoose 都是依赖 native 的。不过在这里mongolian的作者提到 mongolian对 native db class 部分并不调用。看来依赖的程度有所不一。 所测试的内容是 failover。MongoDB 推荐的 failover 方案为 Replica Set，这个架构逻辑上不难理解。至少三个节点，至多七个节点；各个节点可以有 0-99 的优先级等一系列特性让他成为非常优秀的 HA 方案。 测试方法： 插入 N 条数据，并且在插入的过程中将 Primary 进程杀死。查看客户端（node.js）是否正常转移到新的 [...]
Related posts:<ol>
<li><a href='http://latteye.com/2011/10/mongodb-%e7%ac%94-2.html' rel='bookmark' title='MongoDB 笔记 2'>MongoDB 笔记 2</a></li>
<li><a href='http://latteye.com/2011/10/mongodb-note-1.html' rel='bookmark' title='MongoDB 笔记 1'>MongoDB 笔记 1</a></li>
<li><a href='http://latteye.com/2011/10/mongodb-note-3.html' rel='bookmark' title='MongoDB 笔记 3'>MongoDB 笔记 3</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>在对 node.js + MongoDB 做了一周不到的测试之后，我们决定放弃这对组合。放弃的原因有二：</p>
<ol>
<li>MongoDB 对数据的保障性不是我们所需要的。这不是 MongoDB 的错误，这是我们选择产品的错误。我觉得 MongoDB 其实就是放弃了这样的数据保障性才获得了更好的性能。所以才更适合类似 facebook twitter 对消息保障性要求不高，但是量大的应用。</li>
<li>Javascript 的 driver 略显不成熟。其实各类开发速度都很快，同时我对他们的熟悉程度还不够好。所以总的感觉现在还没到用的时候。</li>
</ol>
<p>这里对第二点做个流水账式样的记录，在学习的过程中发现相关的英文和中文资料都比较缺乏。<span id="more-1283"></span></p>
<p>我所测试到的 Driver 有：</p>
<ol>
<ul><a href="https://github.com/christkv/node-mongodb-native" title="node-mongodb-native" target="_blank">node-mongodb-native</a></ul>
<ul><a href="https://github.com/masylum/mongolia" title="Mongolian" target="_blank">mongolian</a></ul>
<ul><a href="https://github.com/LearnBoost/mongoose" title="MongoOSE" target="_blank">mongoose</a></ul>
</ol>
<p>这三个 Driver 里，mongolian 和 mongoose 都是依赖 native 的。不过<a href="https://github.com/marcello3d/node-mongolian/issues/34#issuecomment-1787728" target="_blank">在这里</a>mongolian的作者提到 mongolian对 native db class 部分并不调用。看来依赖的程度有所不一。<br />
所测试的内容是 failover。MongoDB 推荐的 failover 方案为 <a href="http://www.mongodb.org/display/DOCS/Replica+Sets" target="_blank">Replica Set</a>，这个架构逻辑上不难理解。至少三个节点，至多七个节点；各个节点可以有 0-99 的优先级等一系列特性让他成为非常优秀的 HA 方案。</p>
<p><strong>测试方法：</strong> 插入 N 条数据，并且在插入的过程中将 Primary 进程杀死。查看客户端（node.js）是否正常转移到新的 Primary ，并且最终检查数据一致性。可以接受插入不了数据，但是一定要有错误返回。返回错误的数量一定要和数据库内未插入的数据数量一致。</p>
<p><strong>一、native</strong><br />
先给出 native 的测试脚本：</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> mongodb <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mongodb'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> Db <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mongodb'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">Db</span><span style="color: #339933;">,</span>
  Connection <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mongodb'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">Connection</span><span style="color: #339933;">,</span>
  Server <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mongodb'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">Server</span><span style="color: #339933;">,</span>
  ReplSetServers <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mongodb'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ReplSetServers</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> replStat <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> ReplSetServers<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span>
	<span style="color: #003366; font-weight: bold;">new</span> Server<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'172.16.5.151'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">28010</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> auto_reconnect<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
	<span style="color: #003366; font-weight: bold;">new</span> Server<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'172.16.5.152'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">28010</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> auto_reconnect<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
	<span style="color: #003366; font-weight: bold;">new</span> Server<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'172.16.5.153'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">28010</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> auto_reconnect<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
	<span style="color: #009900;">&#123;</span>rs_name<span style="color: #339933;">:</span> <span style="color: #3366CC;">'rs1'</span><span style="color: #009900;">&#125;</span> 
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> db <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Db<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'a'</span><span style="color: #339933;">,</span> replStat<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
db.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>error<span style="color: #339933;">,</span> client<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>error<span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">throw</span> error<span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> collection <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> mongodb.<span style="color: #660066;">Collection</span><span style="color: #009900;">&#40;</span>client<span style="color: #339933;">,</span> <span style="color: #3366CC;">'blogposts'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> test_read<span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'enum elements...'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> start <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> times <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;=</span> t<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
	collection.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">'_id'</span><span style="color: #339933;">:</span>i<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>limit<span style="color: #339933;">:</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">nextObject</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> docs<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> console.<span style="color: #660066;">warn</span><span style="color: #009900;">&#40;</span>err.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #006600; font-style: italic;">//else console.dir(docs);</span>
	    <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">++</span>times <span style="color: #339933;">&gt;=</span> t<span style="color: #009900;">&#41;</span>
		console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'enum finished:cost time:'</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> Date <span style="color: #339933;">-</span> start<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'ms'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> test_write<span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> start <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> times <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'add elements...'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;=</span> t<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	collection.<span style="color: #660066;">insert</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>date<span style="color: #339933;">:</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">getTime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> body<span style="color: #339933;">:</span><span style="color: #3366CC;">'sadf'</span><span style="color: #339933;">,</span> title<span style="color: #339933;">:</span><span style="color: #3366CC;">'abc'</span><span style="color: #339933;">,</span> _id<span style="color: #339933;">:</span>i<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>safe<span style="color: #339933;">:</span><span style="color: #009900;">&#123;</span>w<span style="color: #339933;">:</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> wtimeout<span style="color: #339933;">:</span> <span style="color: #CC0000;">10000</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
                    <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> objects<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> console.<span style="color: #660066;">warn</span><span style="color: #009900;">&#40;</span>err.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">++</span>times <span style="color: #339933;">&gt;=</span> t<span style="color: #009900;">&#41;</span>
	    <span style="color: #009900;">&#123;</span>
		console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'add finished:cost time:'</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> Date <span style="color: #339933;">-</span> start<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'ms'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		test_read<span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #009900;">&#125;</span>
  	<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> wtimes <span style="color: #339933;">=</span> <span style="color: #CC0000;">10000</span><span style="color: #339933;">;</span>
test_write<span style="color: #009900;">&#40;</span>wtimes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #006600; font-style: italic;">//test_read(wtimes);</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>三个 driver 中文档工作做的最好的就是 native 了，<a href="https://github.com/christkv/node-mongodb-native/tree/master/examples" title="native example" target="_blank">example 也比较多</a>。不过作者在 <a href="https://github.com/christkv/node-mongodb-native/blob/master/examples/replSetServersQueries.js" target="_blank">Replica Set 的 examples</a> 中给了个让人很莫名的开头：</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> port1 <span style="color: #339933;">=</span> <span style="color: #CC0000;">27018</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> port2 <span style="color: #339933;">=</span> <span style="color: #CC0000;">27019</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> server <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Server<span style="color: #009900;">&#40;</span>host<span style="color: #339933;">,</span> port<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> server1 <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Server<span style="color: #009900;">&#40;</span>host<span style="color: #339933;">,</span> port1<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> server2 <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Server<span style="color: #009900;">&#40;</span>host<span style="color: #339933;">,</span> port2<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> servers <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Array<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
servers<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> server2<span style="color: #339933;">;</span>
servers<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> server1<span style="color: #339933;">;</span>
servers<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> server<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> replStat <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> ReplSetServers<span style="color: #009900;">&#40;</span>servers<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>对于我这种不写代码的人来说，您老写成这样着实让我纠结了一番⋯⋯</p>
<p><strong>测试结果：</strong> 在插入的过程中将 Primary kill 后大约有 1/3 的概率 node.js crash 了。其余 2/3 的概率 node.js 彻底卡住。MongoDB 端 Primary 正常转移，但未见数据继续插入进来。我很想贴一点 log 上来，但 native driver 真的没有任何 log，就是单纯的卡住了⋯⋯卡住⋯⋯卡⋯⋯</p>
<p><em>Crash log：</em></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>root<span style="color: #000000; font-weight: bold;">@</span>localhost bin<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># ./node ~/native_test.js </span>
<span style="color: #000000;">2</span>
<span style="color: #000000;">3</span>
<span style="color: #000000;">4</span>
add elements...
node: src<span style="color: #000000; font-weight: bold;">/</span>uv-common.c:<span style="color: #000000;">92</span>: uv_err_name: Assertion <span style="color: #000000; font-weight: bold;">`</span><span style="color: #000000;">0</span><span style="color: #ff0000;">' failed.
已放弃</span></pre></div></div>

<p>在经过几天的搜索以后[<a href="https://github.com/christkv/node-mongodb-native/issues/366" target="_blank">1</a> <a href="http://stackoverflow.com/questions/7523404/how-to-turn-off-mongo-in-replica-set-properly-without-db-down" target="_blank">2</a> <a href="http://groups.google.com/group/node-mongodb-native/browse_thread/thread/0ad5c592a4e0f59f" target="_blank">3</a> ] 我发现似乎有人和我做过类似的测试，但是从来没有得到明确的答案。昨天我也将这个问题发到的 native 论坛上，目前还没有人回复。<br />
但是后来又随后开始怀疑自己的脚本，同时看到新的解答[<a href="http://stackoverflow.com/questions/7559442/how-to-reconnect-mongo-automatically-in-node-js-server" target="_blank">4</a>]，于是开始尝试不在一个 db.open 里面写 for，而在 for 里面反复的 db.open 和 db.close。但是没有成功，循环插入10条数据，成功插入的只有第一条。无论有没有 db.close 都是这个现象。这个不工作的代码就不贴上来了，如果有那位做过类似测试希望可以交流一下。</p>
<p><strong>二、mongoose</strong><br />
测试脚本：</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> mongoose <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mongoose'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
mongoose.<span style="color: #660066;">createSetConnection</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mongodb://172.16.5.151:28010/a,mongodb://172.16.5.152:28010/a,mongodb://172.16.5.153:28010/a'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> Schema <span style="color: #339933;">=</span> mongoose.<span style="color: #660066;">Schema</span><span style="color: #339933;">,</span>
    ObjectId <span style="color: #339933;">=</span> Schema.<span style="color: #660066;">ObjectId</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> BlogPost <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Schema<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
<span style="color: #006600; font-style: italic;">//    author    : ObjectId</span>
    _id       <span style="color: #339933;">:</span> Number
  <span style="color: #339933;">,</span> title     <span style="color: #339933;">:</span> String
  <span style="color: #339933;">,</span> body      <span style="color: #339933;">:</span> String
  <span style="color: #339933;">,</span> date      <span style="color: #339933;">:</span> Date
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
mongoose.<span style="color: #660066;">model</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'BlogPost'</span><span style="color: #339933;">,</span> BlogPost<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> post <span style="color: #339933;">=</span> mongoose.<span style="color: #660066;">model</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'BlogPost'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> test_read<span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> start <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> times <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
	console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'enum elements...'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;=</span> t<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">//console.log(&quot;read:&quot;+i);</span>
		post.<span style="color: #660066;">findById</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> doc<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span>
				console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #006600; font-style: italic;">//else</span>
			<span style="color: #006600; font-style: italic;">//	console.log(doc);</span>
			<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">++</span>times <span style="color: #339933;">&gt;=</span> t<span style="color: #009900;">&#41;</span>
			<span style="color: #009900;">&#123;</span>
				<span style="color: #003366; font-weight: bold;">var</span> end <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'enum finished:cost time:'</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>end <span style="color: #339933;">-</span> start<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;ms&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> test_write<span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> start <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">var</span> times <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
	console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'add elements...'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;=</span> t<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #006600; font-style: italic;">//console.log(&quot;write:&quot;+i);</span>
&nbsp;
		<span style="color: #003366; font-weight: bold;">var</span> p <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> post<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		p._id <span style="color: #339933;">=</span> i<span style="color: #339933;">;</span>
		p.<span style="color: #660066;">title</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'abc'</span><span style="color: #339933;">;</span>
		p.<span style="color: #660066;">body</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'sadf'</span><span style="color: #339933;">;</span>
		p.<span style="color: #660066;">date</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">getTime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		p.<span style="color: #660066;">save</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
			<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span>
			<span style="color: #009900;">&#123;</span>
				console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
			<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">++</span>times <span style="color: #339933;">&gt;=</span> t<span style="color: #009900;">&#41;</span>
			<span style="color: #009900;">&#123;</span>
				<span style="color: #003366; font-weight: bold;">var</span> end <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'add finished:cost time:'</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>end <span style="color: #339933;">-</span> start<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;ms&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				test_read<span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> wtimes <span style="color: #339933;">=</span> <span style="color: #CC0000;">10000</span><span style="color: #339933;">;</span>
test_write<span style="color: #009900;">&#40;</span>wtimes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #006600; font-style: italic;">//process.exit(0);</span></pre></div></div>

<p>首先！连接 Replica Set 要用createSetConnection：</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">mongoose.<span style="color: #660066;">createSetConnection</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mongodb://172.16.5.151:28010/a,mongodb://172.16.5.152:28010/a,mongodb://172.16.5.153:28010/a'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>你或许和我一样走过一些弯路[<a href="http://groups.google.com/group/mongoose-orm/browse_thread/thread/eadd5a8f42e4d2b3" target="_blank">5</a> <a href="http://groups.google.com/group/mongoose-orm/browse_thread/thread/eadd5a8f42e4d2b3" target="_blank">6</a>]。</p>
<p><strong>测试结果：</strong> OSE 的测试结果几乎和 native 一样，唯一好一点的是它从来没把 node.js 弄 crash 过。它唯一的反应就是 卡住⋯⋯卡住⋯⋯<br />
OSE 和 native 在这个测试上的区别是，native 一边产生数据一边插入。OSE 先将数据在内存中产生出来以后，再一次插入数据库。而 <a href="http://code.google.com/p/v8/issues/detail?id=847" target="_blank">node.js 存在一个内存限制的问题</a> （一个浏览器有什么理由需要2G的内存呢？），所以当 OSE driver 占用超过 1.9G 内存之后，node.js 不出意料的 crash。</p>
<blockquote><p>PS. google 论坛上有人说可以通过参数让 node.js 支持任何大小的内存。经过我的测试(CentOS 6 x86-64,0.5.x,0.4.x)没有成功过。可工作的最高数值为 1900M。</p></blockquote>
<p>你可以注意到了 native 驱动有一个 auto_reconnect 参数（尽管它没有 reconnect），而 mongoose 脚本里面没看到。OSE 的确也有设置 auto_reconnect 的方式[<a href="https://github.com/LearnBoost/mongoose/issues/306" target="_blank">7</a>]，但是只看到给普通连接设置的方式。没有看到给 Replica Set 用的方式。自己胡乱尝试了几个设置方式无一成功。希望 ose 的作者能再多花点时间在文档方面。另一方面也可以看到，OSE 其实对 native 依赖还是蛮严重的。这种设置方式的出现似乎只是传递给 native 驱动，我猜测 OSE 自己没有对这块做任何处理。</p>
<p><strong>三、mongolian</strong><br />
测试脚本：</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> mongodb <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mongolian'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> server <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> mongodb<span style="color: #009900;">&#40;</span>
    <span style="color: #3366CC;">&quot;172.16.5.151:28010&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;172.16.5.152:28010&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;172.16.5.153:28010&quot;</span>
<span style="color: #009900;">&#41;</span>
<span style="color: #003366; font-weight: bold;">var</span> db <span style="color: #339933;">=</span> server.<span style="color: #660066;">db</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span>
<span style="color: #003366; font-weight: bold;">var</span> blogposts <span style="color: #339933;">=</span> db.<span style="color: #660066;">collection</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;blogposts&quot;</span><span style="color: #009900;">&#41;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> test_read<span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'enum elements...'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> start <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> times <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;=</span> t<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
	blogposts.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">'_id'</span><span style="color: #339933;">:</span>i<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>limit<span style="color: #339933;">:</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">nextObject</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> docs<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> console.<span style="color: #660066;">warn</span><span style="color: #009900;">&#40;</span>err.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #006600; font-style: italic;">//else console.dir(docs);</span>
	    <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">++</span>times <span style="color: #339933;">&gt;=</span> t<span style="color: #009900;">&#41;</span>
		console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'enum finished:cost time:'</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> Date <span style="color: #339933;">-</span> start<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'ms'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> test_write<span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> start <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #339933;">;</span>
  <span style="color: #003366; font-weight: bold;">var</span> times <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
  console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'add elements...'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;=</span> t<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  	blogposts.<span style="color: #660066;">insert</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>date<span style="color: #339933;">:</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">getTime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> body<span style="color: #339933;">:</span><span style="color: #3366CC;">'sadf'</span><span style="color: #339933;">,</span> title<span style="color: #339933;">:</span><span style="color: #3366CC;">'abc'</span><span style="color: #339933;">,</span> _id<span style="color: #339933;">:</span>i<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
                    <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span> objects<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>err<span style="color: #009900;">&#41;</span> console.<span style="color: #660066;">warn</span><span style="color: #009900;">&#40;</span>err.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">++</span>times <span style="color: #339933;">&gt;=</span> t<span style="color: #009900;">&#41;</span>
	    <span style="color: #009900;">&#123;</span>
		console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'add finished:cost time:'</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> Date <span style="color: #339933;">-</span> start<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'ms'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		test_read<span style="color: #009900;">&#40;</span>t<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #009900;">&#125;</span>
  	<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> wtimes <span style="color: #339933;">=</span> <span style="color: #CC0000;">10000</span><span style="color: #339933;">;</span>
test_write<span style="color: #009900;">&#40;</span>wtimes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #006600; font-style: italic;">//test_read(wtimes);</span></pre></div></div>

<p><strong>测试结果：</strong> mongolian(以下简称lian) 的反应是这三个驱动中最好的。首先当开启 node 的时候，lian 会给出 debug 信息，明确告诉你他连接到了哪台 mongodb，作者也明确说了这个 log 是为 Replica Set 做的 [<a href="https://github.com/marcello3d/node-mongolian/issues/36" target="_blank">8</a> <a href="https://github.com/marcello3d/node-mongolian/issues/13" target="_blank">9</a>]。当 Primary 被 kill 掉之后，lian 会告诉你连接丢失。在后面的插入lian会明确的告诉你插入失败，并且是每一次插入就给出一个 log，而且程序会一路走下去，不会卡住。</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>root<span style="color: #000000; font-weight: bold;">@</span>localhost ~<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># node lian_test.js </span>
add elements...
<span style="color: #7a0874; font-weight: bold;">&#91;</span>debug<span style="color: #7a0874; font-weight: bold;">&#93;</span> mongo:<span style="color: #000000; font-weight: bold;">//</span>172.16.5.151:<span style="color: #000000;">28010</span>: Disconnected
<span style="color: #7a0874; font-weight: bold;">&#91;</span>error<span style="color: #7a0874; font-weight: bold;">&#93;</span> mongo:<span style="color: #000000; font-weight: bold;">//</span>172.16.5.151:<span style="color: #000000;">28010</span>: Error: ECONNREFUSED, Connection refused
<span style="color: #7a0874; font-weight: bold;">&#91;</span>debug<span style="color: #7a0874; font-weight: bold;">&#93;</span> mongo:<span style="color: #000000; font-weight: bold;">//</span>172.16.5.152:<span style="color: #000000;">28010</span>: Connected
<span style="color: #7a0874; font-weight: bold;">&#91;</span>debug<span style="color: #7a0874; font-weight: bold;">&#93;</span> mongo:<span style="color: #000000; font-weight: bold;">//</span>172.16.5.153:<span style="color: #000000;">28010</span>: Connected
<span style="color: #7a0874; font-weight: bold;">&#91;</span>debug<span style="color: #7a0874; font-weight: bold;">&#93;</span> mongo:<span style="color: #000000; font-weight: bold;">//</span>172.16.5.152:<span style="color: #000000;">28010</span>: Initialized <span style="color: #c20cb9; font-weight: bold;">as</span> secondary
<span style="color: #7a0874; font-weight: bold;">&#91;</span>debug<span style="color: #7a0874; font-weight: bold;">&#93;</span> mongo:<span style="color: #000000; font-weight: bold;">//</span>172.16.5.153:<span style="color: #000000;">28010</span>: Initialized <span style="color: #c20cb9; font-weight: bold;">as</span> primary
<span style="color: #7a0874; font-weight: bold;">&#91;</span>info<span style="color: #7a0874; font-weight: bold;">&#93;</span> mongo:<span style="color: #000000; font-weight: bold;">//</span>172.16.5.153:<span style="color: #000000;">28010</span>: Connected to primary
<span style="color: #7a0874; font-weight: bold;">&#91;</span>debug<span style="color: #7a0874; font-weight: bold;">&#93;</span> Finished scanning... primary? mongo:<span style="color: #000000; font-weight: bold;">//</span>172.16.5.153:<span style="color: #000000;">28010</span></pre></div></div>

<p>我觉得 lian 的这种工作模式可以从它的代码编写方式里面体现出来。lian 的代码里面不存在打开一个 connection 或者 db.open 这样的概念，所以我估计 lian 是每一次 insert 就会尝试打开一次 connection。虽然他没有再次找到正确的 Primary，但至少他知道自己连接丢失了。<br />
但是 lian 没能再次找到正确的 Primary 可能意味着他先打开了一个 ConnectionPool （你可以通过 poolSize 在 native 里面设置 pool 的大小），只有打开 ConnectionPool 的时候才会尝试去做 Primary 判断。<br />
另外 lian 的插入速度也不错，感觉比 OSE 好，几乎和 native 一样。</p>
<p>实验做到后面，我极度怀疑自己的测试脚本写的不对。因为 native 是有 auto_reconnect 的参数的，但是缺没有工作。作者应该考虑了这个问题的。<br />
而也肯定有一种方式让我在 for 里面打开 connection 、写完、关闭 connection。只是我现在没找到正确的写法。<br />
希望有经验的朋友给予一些帮助。<br />
<img src="http://latteye.com/gmail.png" alt="gmail" /></p>
<p>虽然已经决定在最近做的项目中不再使用 MongoDB 但我会持续关注这款数据。</p>
<p>Related posts:</p><ol>
<li><a href='http://latteye.com/2011/10/mongodb-%e7%ac%94-2.html' rel='bookmark' title='MongoDB 笔记 2'>MongoDB 笔记 2</a></li>
<li><a href='http://latteye.com/2011/10/mongodb-note-1.html' rel='bookmark' title='MongoDB 笔记 1'>MongoDB 笔记 1</a></li>
<li><a href='http://latteye.com/2011/10/mongodb-note-3.html' rel='bookmark' title='MongoDB 笔记 3'>MongoDB 笔记 3</a></li>
</ol>]]></content:encoded>
			<wfw:commentRss>http://latteye.com/2011/10/mongodb-javascript-driver.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

