<?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>一个故事@MySQL DBA &#187; Linux</title>
	<atom:link href="http://www.orczhou.com/index.php/tag/linux/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.orczhou.com</link>
	<description>一个故事@MySQL DBA</description>
	<lastBuildDate>Tue, 20 Dec 2011 15:51:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>TCP/IP重传超时--RTO</title>
		<link>http://www.orczhou.com/index.php/2011/10/tcpip-protocol-start-rto/</link>
		<comments>http://www.orczhou.com/index.php/2011/10/tcpip-protocol-start-rto/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 12:19:27 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[技术细节]]></category>
		<category><![CDATA[retransmission timeout]]></category>
		<category><![CDATA[RTO]]></category>
		<category><![CDATA[TCP]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=3162</guid>
		<description><![CDATA[<p>概述：本文讨论主机在发送一个TCP数据包后，如果迟迟没有收到ACK，主机多久后会重传这个数据包。主机从发出数据包到第一次TCP重传开始，<a href="http://zh.wikipedia.org/wiki/RFC#RFC.E6.96.87.E4.BB.B6.E7.9A.84.E7.94.A2.E7.94.9F">RFC</a>中这段时间间隔称为retransmission timeout，缩写做RTO。本文会先看看RFC中如何定义RTO，然后看看Linux中如何实现。<strong>本文旨在分享</strong>：当遇到了TCP层问题改如何去查找、阅读文档，该如何去在Linux源码中寻求答案。</p>
<div class="myt1">1. 起源</div>
<p>在分析MySQL Semi-sync故障时，我们用Tcpdump+Wireshark（感谢淘宝雕梁）抓住当时的网络包传送细节，观察到了一次TCP重传最终导致了Semi-sync超时：</p>
<pre>
<div class="mycode">第一次传输
13:55:11.893291 master => slave	Binlog pos:319890197
重传：
13:55:12.094596	master => slave	Binlog pos:319890197
</div>
</pre>
<p>看到两次传送间隔约201毫秒，即第一次传输201毫秒后，还没有收到ACK响应，TCP认为传输超时，开始重传。</p>
<p>疑问：host和host之间的RTT大约是0.5毫秒，为什么第一次重传需要等200毫秒？（我希望是&#60;20ms）socket程序可以配置吗RTO吗？TCP有参数可配置RTO吗？</p>
<div class="myt1">2. Google/书籍/RFC</div>
<p>翻开TCP/IP详解找到关于TCP Retransmission章节，较详细的介绍TCP的超时机制，书中是个概述，于是又找到RFC1122。</p>
<p>RFC1122的4.2.2.15和4.2.3.1都介绍了Retransmission Timeout的处理（说来惭愧，这是第一次阅读TCP相关RFC）。</p>
<p>在<a href="http://www.ietf.org/rfc.html">RFC中搜索</a>Retransmission发现RFC 793 1122 2988 6298都有对重传算法、和初次重传超时的描述。于是开始阅读这个四个RFC，耗时约2小时，了解了大致的重传超时算法。[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2011/10/tcpip-protocol-start-rto/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>概述：本文讨论主机在发送一个TCP数据包后，如果迟迟没有收到ACK，主机多久后会重传这个数据包。主机从发出数据包到第一次TCP重传开始，<a href="http://zh.wikipedia.org/wiki/RFC#RFC.E6.96.87.E4.BB.B6.E7.9A.84.E7.94.A2.E7.94.9F">RFC</a>中这段时间间隔称为retransmission timeout，缩写做RTO。本文会先看看RFC中如何定义RTO，然后看看Linux中如何实现。<strong>本文旨在分享</strong>：当遇到了TCP层问题改如何去查找、阅读文档，该如何去在Linux源码中寻求答案。</p>
<div class="myt1">1. 起源</div>
<p>在分析MySQL Semi-sync故障时，我们用Tcpdump+Wireshark（感谢淘宝雕梁）抓住当时的网络包传送细节，观察到了一次TCP重传最终导致了Semi-sync超时：</p>
<pre>
<div class="mycode">第一次传输
13:55:11.893291 master => slave	Binlog pos:319890197
重传：
13:55:12.094596	master => slave	Binlog pos:319890197
</div>
</pre>
<p>看到两次传送间隔约201毫秒，即第一次传输201毫秒后，还没有收到ACK响应，TCP认为传输超时，开始重传。</p>
<p>疑问：host和host之间的RTT大约是0.5毫秒，为什么第一次重传需要等200毫秒？（我希望是<20ms）socket程序可以配置吗RTO吗？TCP有参数可配置RTO吗？</p>
<div class="myt1">2. Google/书籍/RFC</div>
<p>翻开TCP/IP详解找到关于TCP Retransmission章节，较详细的介绍TCP的超时机制，书中是个概述，于是又找到RFC1122。</p>
<p>RFC1122的4.2.2.15和4.2.3.1都介绍了Retransmission Timeout的处理（说来惭愧，这是第一次阅读TCP相关RFC）。</p>
<p>在<a href="http://www.ietf.org/rfc.html">RFC中搜索</a>Retransmission发现RFC 793 1122 2988 6298都有对重传算法、和初次重传超时的描述。于是开始阅读这个四个RFC，耗时约2小时，了解了大致的重传超时算法。<span id="more-3162"></span></p>
<div class="myt1">3. RFC中如何计算RTO(Retransmission Timeout)</div>
<div class="myt2">3.1 RFC-793如何计算RTO</div>
<p>概述：先根据该socket的RTT计算出SRTT（Smoothed Round Trip Time），然后根据一个最大、最小超时时间确定当前RTO。说明：srtt可以理解为“平滑化”的RTT，即在保持计算简单的情况尽量考虑历史RTT。</p>
<p>详细计算：SRTT = ( ALPHA * SRTT ) + ((1-ALPHA) * RTT)</p>
<p>基于SRTT，我们再来计算RTO：RTO = min[UBOUND,max[LBOUND,(BETA*SRTT)]]</p>
<p>UBOUND是RTO上线，ALPHA是平滑因子（smoothing factor， e.g., .8 to .9），BETA是一个延迟方差因子（BETA is a delay variance factor (e.g., 1.3 to 2.0)）。</p>
<p>仔细看这两个公式大概就能理解了RTO的计算了。</p>
<p>这里对上面两个公式做一个简单的注释：公式1中计算SRTT，ALPHA越接近于0，则表示SRTT越相信这一次的RTT；越接近于1，则表示SRTT越相信上次统计的RTT。公式二给RTO分别设置了一个上限和下限。</p>
<div class="myt2">3.2 RTO重传间隔是指数增加的</div>
<p>上面我们介绍的是初次重传时的RTO，如果重传后还没收到另一端的响应，下一次重传RTO则会指数增加，例如第一次重传RTO是1，之后分别2，4，8，16...。</p>
<div class="myt2">3.3 RFC-2988和RFC-6298中的RTO计算</div>
<p>在RFC-2988和RFC-6298中又重新改进了RTO的计算方法，Linux中的实现即使参考RFC-2988。算法核心公式：</p>
<pre>
<div class="mycode">初始：
SRTT <- R
RTTVAR <- R/2
RTO <- SRTT + max (G, K*RTTVAR)
where K = 4.

根据RTT计算SRTT：
RTTVAR <- (1 - beta) * RTTVAR + beta * |SRTT - R'|
SRTT <- (1 - alpha) * SRTT + alpha * R'

最后RTO：
RTO <- SRTT + max (G, K*RTTVAR)
</div>
</pre>
<div class="myt1">4. Linux中的RTO(Retransmission Timeout)</div>
<p>这里说的是RHEL5.4的2.6.18内核，RFC-2988实现参考net/ipv4/tcp_input.c中的tcp_rtt_estimator和tcp_set_rto。可以看到，在Linux中alpha=1/8，RTO最小为TCP_RTO_MIN。因为我们的系统中RTT总是很小，所以RTO取值总是能够取到TCP_RTO_MIN。</p>
<p>在看看TCP_RTO_MIN在Linux中的定义：</p>
<pre>
<div class="mycode">123#define TCP_RTO_MAX     ((unsigned)(120*HZ))
124#define TCP_RTO_MIN     ((unsigned)(HZ/5))
</div>
</pre>
<p>(这里简单的介绍介绍一下HZ，HZ可以理解为1s，所以120*HZ就是120秒，HZ/5就是200ms。详细的：HZ表示CPU一秒种发出多少次时间中断--IRQ-0，Linux中通常用HZ来做时间片的计算，<a href="http://blog.csdn.net/bdc995/article/details/4144031">参考</a>)</p>
<div class="myt1">5. 其他：Linux中可配置重传参数</div>
<p>/proc/sys/net/ipv4/tcp_retries1  (integer; default: 3)</p>
<p>TCP尝试了3次（tcp_retries1默认3）重传后，还没有收到ACK的话，则后续每次重传都需要network layer先更新路由。</p>
<p>/proc/sys/net/ipv4/tcp_retries2  (integer; default: 15)</p>
<p>TCP默认最多做15次重传。根据RTO(retransmission timeout)不同，最后一次重传间隔大概是13到30分钟左右。如果15次重传都做完了，TCP/IP就会告诉应用层说：“搞不定了，包怎么都传不过去！”</p>
<div class="myt1">6. 最后</div>
<p>回答前面的问题：即使RTT很小（0.8ms），但是因为RTO有下限，最小必须是200ms，所以这是RTT再小也白搭；RTO最小值是内核编译是决定的，socket程序中无法修改，Linux TCP也没有任何参数可以改变这个值。</p>
<p>好了，不容易。</p>
<p><script type="text/javascript" src="http://www.xiami.com/widget/player-single?uid=318706&#038;sid=382457&#038;mode=js"></script></p>
<p>广告：<a href="http://www.orczhou.com/index.php/projects/we-are-hunting-mysql-hacker/">我们寻找靠谱的人</a> | <a href="http://www.orczhou.com/index.php/wish-list/">感谢作者</a></p>
<p>参考文献</p>
<p>1. RFC 1122 ... (<a href="http://www.ietf.org/rfc.html">在哪儿查找RFC</a>) TCP协议相关的RFC：<br />
RFC 675 - Specification of Internet Transmission Control Program, December 1974 Version<br />
RFC 793 - TCP v4<br />
RFC 1122 - includes some error corrections for TCP<br />
RFC 1323 - TCP-Extensions<br />
RFC 1379 - Extending TCP for Transactions—Concepts<br />
RFC 1948 - Defending Against Sequence Number Attacks<br />
RFC 2018 - TCP Selective Acknowledgment Options<br />
RFC 2988 - Computing TCP's Retransmission Timer<br />
RFC 4614 - A Roadmap for TCP Specification Documents<br />
RFC 5681 - TCP Congestion Control</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2011/10/tcpip-protocol-start-rto/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Linux Top命令学习</title>
		<link>http://www.orczhou.com/index.php/2010/12/linux-top-tips/</link>
		<comments>http://www.orczhou.com/index.php/2010/12/linux-top-tips/#comments</comments>
		<pubDate>Wed, 15 Dec 2010 15:43:57 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=2726</guid>
		<description><![CDATA[<p>也忘了第一次用Top观察Linux运行状态是什么时候了，不过最近吧Top的文档收获不少。</p>
<div class="myt1">1. 有用的命令top-z-x</div>
<div class="mycode">
<pre>
z    :打开/关闭彩色显示
x    :高亮显示排序列
</pre>
</div>
<p>在使用top命令后，“先按z键，再按x键”，这时屏幕会彩色显示输出，白色显示的列是当前排序的列；偶尔还会有一些[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2010/12/linux-top-tips/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>也忘了第一次用Top观察Linux运行状态是什么时候了，不过最近吧Top的文档收获不少。</p>
<div class="myt1">1. 有用的命令top-z-x</div>
<div class="mycode">
<pre>
z    :打开/关闭彩色显示
x    :高亮显示排序列
</pre>
</div>
<p>在使用top命令后，“先按z键，再按x键”，这时屏幕会彩色显示输出，白色显示的列是当前排序的列；偶尔还会有一些白色显示行，这些行是当前正在运行进程。使用该参数可以帮助我们更清楚的看到排序列。例如，我想按照cpu使用排序来查看进程：</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/5263726748/" title="top-z-x by orczhou, on Flickr"><img src="http://farm6.static.flickr.com/5007/5263726748_ea49a86290.jpg" width="500" height="176" alt="top-z-x" /></a></p>
<p>使用了top-z-x命令后是不是看得清晰了一些:)</p>
<div class="myt1">2. 有用的命令top-1</div>
<div class="mycode">
<pre>
1    :SMP的系统，会单独显示各个CPU的运行状态
</pre>
</div>
<p><a href="http://www.flickr.com/photos/26825745@N06/5263751592/" title="top-1 by orczhou, on Flickr"><img src="http://farm6.static.flickr.com/5286/5263751592_016743a967.jpg" width="287" height="299" alt="top-1" /></a></p>
<div class="myt1">3. 选择排序列top-z-x-&lt;</div>
<div class="mycode">
<pre>
<    :改变排序列
>    :改变排序列
</pre>
</div>
<p>top-z-x-&lt; 试试就知道是什么意思了:) 。例如，默认是按照cpu使用率排序的，现在我想看看安装使用的虚拟内存排序看看，使用命令top-z-x-&lt;-&lt;-&lt;-&lt;-&lt; ：</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/5263760668/" title="top-z-x-lt by orczhou, on Flickr"><img src="http://farm6.static.flickr.com/5004/5263760668_3278706d02.jpg" width="500" height="196" alt="top-z-x-lt" /></a></p>
<div class="myt1">4. 其他技巧</div>
<div class="mycode">
<pre>
W    :把当前配置文件到home目录下.toprc配置文件中
F or O :支持更强的选择排序列的方式

-b   :参数可以帮你在脚本中使用top命令
-n   :配合-b使用，表示重新刷新一定次数后退出
-d   :刷新延时时间。例如-d 5 表示top每隔5秒刷新一次。（默认是3秒）
</pre>
</div>
<p>就这些吧，更多请查看top-h或者<a href="http://en.wikipedia.org/wiki/RTFM">RTFM</a>。</p>
<p>最后，各位看官，工作之余别忘了多多运动，没什么比健康更重要了:)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2010/12/linux-top-tips/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Flashcace安装 How-to</title>
		<link>http://www.orczhou.com/index.php/2010/10/how-to-setup-flashcace/</link>
		<comments>http://www.orczhou.com/index.php/2010/10/how-to-setup-flashcace/#comments</comments>
		<pubDate>Fri, 08 Oct 2010 10:28:44 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Flashcache]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=2503</guid>
		<description><![CDATA[<p><a href="http://www.facebook.com/note.php?note_id=388112370932">Flashcache</a>的安装在其<a href="http://github.com/facebook/flashcache/blob/master/README">README</a>和<a href="http://github.com/facebook/flashcache/blob/master/README-CentOS5.4">README-CentOS5.4</a>已经有一个很详细的说明了，但是实际操作并不是很顺利，而且有些同事表示在编译过程中<a href="http://www.orczhou.com/index.php/2010/09/flachcache-first-view/#comment-1310">仍遇到了一些问题</a>，这里详细的记录一下自己的编译、安装过程。</p>
<div class="myt1">1. 环境说明</div>
<p>使用的是RHEL5.4的系统：</p>
<div class="mycode">$cat /etc/issue<br />
Red Hat Enterprise Linux Server release 5.4 (Tikanga)<br />
$uname -a<br />
Linux myhost 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
</div>
<p>[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2010/10/how-to-setup-flashcace/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.facebook.com/note.php?note_id=388112370932">Flashcache</a>的安装在其<a href="http://github.com/facebook/flashcache/blob/master/README">README</a>和<a href="http://github.com/facebook/flashcache/blob/master/README-CentOS5.4">README-CentOS5.4</a>已经有一个很详细的说明了，但是实际操作并不是很顺利，而且有些同事表示在编译过程中<a href="http://www.orczhou.com/index.php/2010/09/flachcache-first-view/#comment-1310">仍遇到了一些问题</a>，这里详细的记录一下自己的编译、安装过程。</p>
<div class="myt1">1. 环境说明</div>
<p>使用的是RHEL5.4的系统：</p>
<div class="mycode">$cat /etc/issue<br />
Red Hat Enterprise Linux Server release 5.4 (Tikanga)<br />
$uname -a<br />
Linux myhost 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
</div>
<p><span id="more-2503"></span></p>
<div class="myt1">2. 需要的RPM包</div>
<p>安装基本工具包：rpm-build redhat-rpm-config unifdef。一般情况这三个包都是安装过的，检查一下即可。</p>
<div class="mycode">$sudo yum install rpm-build<br />
Package rpm-build-4.4.2.3-18.el5.x86_64 already installed and latest version<br />
$sudo yum install redhat-rpm-config<br />
Package redhat-rpm-config-8.0.45-32.el5.noarch already installed and latest version<br />
$sudo yum install unifdef<br />
Package unifdef-1.171-5.fc6.x86_64 already installed and latest version</div>
<div class="myt1">3. 下载并安装源码包</div>
<p>现在的RHEL发行版中，已经不再带源码包，所以需要单独下载，供Flashcache编译使用。</p>
<div class="myt2">3.1 准备目录</div>
<div class="mycode">[supu@host]$ cd<br />
[supu@host]$ mkdir -p rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}<br />
[supu@host]$ echo '%_topdir %(echo $HOME)/rpmbuild' &gt; .rpmmacros</div>
<div class="myt2">3.2 下载源码包</div>
<p>可以在<a href="ftp://ftp.redhat.com/pub/redhat/linux/enterprise/5Server/en/os/SRPMS">ftp://ftp.redhat.com/</a>下载到对应的源码包。这里的内核版本号是：</p>
<div class="mycode">$uname -r<br />
2.6.18-164.el5</div>
<p>所以需要下载的是kernel-2.6.18-164.el5.src.rpm，完整的URL是：</p>
<div class="mycode">ftp://ftp.redhat.com/pub/redhat/linux/enterprise/5Server/en/os/SRPMS/kernel-2.6.18-164.el5.src.rpm</div>
<p>注：最好<a href="http://sitka.triumf.ca/pub/linux/redhat-mirror2.html">选择合适</a>的镜像下载，速度会差很多的。</p>
<div class="myt2">3.3 安装源码包</div>
<p>有了前面的目录准备，现在可以安装源码包了</p>
<div class="mycode">sudo rpm -i kernel-2.6.18-164.el5.src.rpm<br />
cd ~/rpmbuild/SPECS<br />
rpmbuild -bp --target=`uname -m` kernel-2.6.spec 2> prep-err.log | tee prep-out.log</div>
<p>OK，这时候源码包就安装到了如下目录：/home/supu/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18.x86_64</p>
<div class="myt2">3.4 准备模块编译</div>
<p>在源码目录执行如下命令，主备Flashcache模块编译</p>
<div class="mycode">cd ~/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18.x86_64<br />
make oldconfig<br />
make prepare<br />
make modules_prepare</div>
<div class="myt1">4. 编译Flashcache</div>
<p>可以在<a href="http://github.com/facebook/flashcache">github</a>上下载Flashcache的源代码，和Linux源码一起编译，编译完成后会生成三个可执行程序和一个可动态加载的内核模块：</p>
<div class="mycode">flashcache_create<br />
flashcache_load<br />
flashcache_destroy<br />
flashcache.ko</div>
<div class="myt2">4.1 下载并准备编译</div>
<p>在在<a href="http://github.com/facebook/flashcache">github</a>上可以下载到Flashcache最新的源码。这里下载的是flashcache-1.0.11，解压后，有如下目录：</p>
<div class="mycode">[supu@host facebook-flashcache-15adea8]$ ls<br />
doc  flashcache-wt  LICENSE  Makefile  README  README-CentOS5.4  README-DKMS  src</div>
<p>其中src包含了普通的Flashcache（这里的普通指的是Write-back版本的Flashcache），flashcache-wt包含了Write-Through版本的源码；文件README-CentOS5.4中包含了在RHEL5.4下编译的注意事项，本文主要参考该文件。</p>
<p>按照README-CentOS5.4中的说明，修改文件src/Makefile，将行EXTRA_CFLAGS（第一行），用如下内容替换：</p>
<pre>
<div class="mycode">EXTRA_CFLAGS=-I$(KERNEL_TREE)/drivers/md -I$(KERNEL_TREE)/include/linux  -I./</div>
</pre>
<div style="color:red">注意：这里没有换行。</div>
<div class="myt2">4.2 编译之</div>
<div class="mycode">make KERNEL_TREE=/home/supu/rpmbuild/BUILD/kernel-2.6.18/linux-2.6.18.x86_64/</div>
<div class="myt2">4.3 动态加载模块</div>
<p>最后需要将模块flashcache.ko加载到内核，这里可以将flashcache.ko拷贝到相应目录：</p>
<div class="mycode">sudo cp flashcache.ko /lib/modules/2.6.18-164.el5/kernel/drivers/block</div>
<p>或者使用insmod命令，动态加载之：</p>
<div class="mycode">sudo insmod flashcache.ko </div>
<p>Job Done! Enjoy!</p>
<p>参考：</p>
<p>1. <a href="http://github.com/facebook/flashcache/blob/master/README-CentOS5.4">Flashcache README-CentOS5.4</a></p>
<p>2. <a href="http://github.com/facebook/flashcache/blob/master/README">Flashcache README</a></p>
<p>3. <a href="http://www.cyberciti.biz/faq/rhel5-installing-kernel-source-code/">Redhat enterprise Linux / CentOS installing kernel source code</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2010/10/how-to-setup-flashcace/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flachcache初探</title>
		<link>http://www.orczhou.com/index.php/2010/09/flachcache-first-view/</link>
		<comments>http://www.orczhou.com/index.php/2010/09/flachcache-first-view/#comments</comments>
		<pubDate>Mon, 27 Sep 2010 03:38:34 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Flashcache]]></category>
		<category><![CDATA[图解]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=2368</guid>
		<description><![CDATA[<p>Flashcache是Facebook技术团队的又一力作，最初是为加速MySQL设计的。Flashcache是在Linux层面的，所以任何受磁盘IO困绕的软件或应用都可以方便的使用之。</p>
<div class="myt1">1. Why Flashcache</div>
<p>随着时间的流逝，网站上的数据一直在不停的积累。如果你经营的只是一个博客的话，这不会是问题，因为10G的空间，大概就够你写一辈子了（如果放在硬盘上，其实一辈子很短）。如果你恰巧在一个快速增长的公司，数据会越来越多，从MB，到GB，再到TB。</p>
<p>如果将这些数据全部放在大容量的SATA、SAS盘上时，会发现性能（响应时间）不够；如果全放在SSD上时，又会发现成本很高。即使公司能够大气到都放到SSD上，你会发现1TB的数据里面可能只有200G是经常被访问的，300G可能偶尔被访问到，最后剩下的500G可能已经成为历史数据了，几乎不被访问到，如果全部都放在SSD上有略有浪费。于是就有了<a href="http://www.facebook.com/note.php?note_id=388112370932">Flashcache</a>。</p>
<p>Flashcache一个非常不错的软件（准确的说是一个<a href="http://tldp.org/LDP/lkmpg/2.6/html/">Linux的模块</a>），可以动态加载。Flashcache通过在文件系统（VFS）和设备驱动之间新增了一次缓存层，来实现对热门的缓存。Flashcache是另一种缓存，一般用SSD作为介质的缓存（一般的缓存用的是内存），通过将传统硬盘上的热门数据缓存到SSD上，然后利用SSD优秀的读性能，来加速系统。这个方法较之内存缓存，没有内存快，但是空间可以比内存大很多。</p>
<p>本文是一个关于Flashcache的初步介绍。[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2010/09/flachcache-first-view/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>Flashcache是Facebook技术团队的又一力作，最初是为加速MySQL设计的。Flashcache是在Linux层面的，所以任何受磁盘IO困绕的软件或应用都可以方便的使用之。</p>
<div class="myt1">1. Why Flashcache</div>
<p>随着时间的流逝，网站上的数据一直在不停的积累。如果你经营的只是一个博客的话，这不会是问题，因为10G的空间，大概就够你写一辈子了（如果放在硬盘上，其实一辈子很短）。如果你恰巧在一个快速增长的公司，数据会越来越多，从MB，到GB，再到TB。</p>
<p>如果将这些数据全部放在大容量的SATA、SAS盘上时，会发现性能（响应时间）不够；如果全放在SSD上时，又会发现成本很高。即使公司能够大气到都放到SSD上，你会发现1TB的数据里面可能只有200G是经常被访问的，300G可能偶尔被访问到，最后剩下的500G可能已经成为历史数据了，几乎不被访问到，如果全部都放在SSD上有略有浪费。于是就有了<a href="http://www.facebook.com/note.php?note_id=388112370932">Flashcache</a>。</p>
<p>Flashcache一个非常不错的软件（准确的说是一个<a href="http://tldp.org/LDP/lkmpg/2.6/html/">Linux的模块</a>），可以动态加载。Flashcache通过在文件系统（VFS）和设备驱动之间新增了一次缓存层，来实现对热门的缓存。Flashcache是另一种缓存，一般用SSD作为介质的缓存（一般的缓存用的是内存），通过将传统硬盘上的热门数据缓存到SSD上，然后利用SSD优秀的读性能，来加速系统。这个方法较之内存缓存，没有内存快，但是空间可以比内存大很多。</p>
<p>本文是一个关于Flashcache的初步介绍。<span id="more-2368"></span></p>
<div class="myt1">2. 谁适合用Flashcache</div>
<p>数据量很大（例如4TB），热门数据也很大（800GB），不必要或者不舍得全部买内存来缓存。</p>
<div class="myt1">3. 谁<strong>不</strong>适合用Flashcache</div>
<p>数据量不大的话，一般Flashcache就没什么用武之地了，内存就可以帮你解决问题了；</p>
<p>不差钱，买内存呗；</p>
<p>另外Flashcache的加入也使得系统的复杂度增加了一层，如果你坚持<a href="http://en.wikipedia.org/wiki/KISS_principle">KISS原则</a>（Keep it simple, Stupid!），也可以弃用之。</p>
<div class="myt1">4. 基本原理图</div>
<p><a href="http://www.flickr.com/photos/26825745@N06/5023251788/" title="Flashcache_orczhou by orczhou, on Flickr"><img src="http://farm5.static.flickr.com/4146/5023251788_f67a46dc7d.jpg" width="500" height="296" alt="Flashcache_orczhou" /></a></p>
<p>上图中，Flashcache将普通的SAS盘（/dev/sda）和一个高速的SSD(/dev/sdb)虚拟成一个带缓存的块设备（/dev/mapper/cachedev）。后续还将会有更多关于Flashcache相关的文章出现，敬请期待。</p>
<div class="myt1">5. Flashcache是否只是一个过渡产品</div>
<p>对于当前，PCI接口的SSD价格还十分昂贵，而随着时间的推移，价格会降；另外，根据<a href="http://zh.wikipedia.org/zh-hk/%E6%91%A9%E5%B0%94%E5%AE%9A%E5%BE%8B">摩尔定律</a>，未来会有更快的设备出现，所以Flashcache是一个“持久的”产品，还只是一个过渡软件，这并不好说。</p>
<p>关注未来新技术的发展吧:)</p>
<p>参考：</p>
<p>1. <a href="http://github.com/facebook/flashcache/">Facebook / Flashcache</a></p>
<p>2. <a href="http://www.facebook.com/note.php?note_id=388112370932">Releasing Flashcache of Facebook</a></p>
<p>3. <a href="http://github.com/facebook/flashcache/blob/master/doc/flashcache-doc.txt">flashcache-doc.txt</a></p>
<p>PS：写完整篇文章，最大的收获是：发现人的一生其实很短、很短，可能连1GB都不到。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2010/09/flachcache-first-view/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Linux下使用od查看文件</title>
		<link>http://www.orczhou.com/index.php/2010/08/linux-od-data-file/</link>
		<comments>http://www.orczhou.com/index.php/2010/08/linux-od-data-file/#comments</comments>
		<pubDate>Sun, 22 Aug 2010 10:44:35 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=2407</guid>
		<description><![CDATA[<p><font color="red">
<pre>        "不积跬步，无以至千里"
                                 《劝学》
</pre>
<p></p></font></p>
<p>查看文本文件使用vim/less就足够了，但如果想要查看一些其他二进制文件（例如DB的数据文件、程序的二进制代码）则借助于od/hexdump这些工具会很方便，这里会通过一些实例来详细介绍od命令的相关参数。</p>
<div class="myt1">1. od参数详解</div>
<pre>
<div class="mycode">$od -j 49152 -N 38 -w4 -A d -t x1 -v tmp_test.ibd
0049152 fd 6f fb 70
0049156 00 00 00 03
0049160 ff ff ff ff
0049164 ff ff ff ff
0049168 00 00 00 03
0049172 ba 92 ac 0c
0049176 45 bf 00 00
0049180 00 00 00 00
0049184 00 00 00 00
</div>
</pre>
<p>[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2010/08/linux-od-data-file/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p><font color="red">
<pre>        "不积跬步，无以至千里"
                                 《劝学》
</pre>
<p></font></p>
<p>查看文本文件使用vim/less就足够了，但如果想要查看一些其他二进制文件（例如DB的数据文件、程序的二进制代码）则借助于od/hexdump这些工具会很方便，这里会通过一些实例来详细介绍od命令的相关参数。</p>
<div class="myt1">1. od参数详解</div>
<pre>
<div class="mycode">$od -j 49152 -N 38 -w4 -A d -t x1 -v tmp_test.ibd
0049152 fd 6f fb 70
0049156 00 00 00 03
0049160 ff ff ff ff
0049164 ff ff ff ff
0049168 00 00 00 03
0049172 ba 92 ac 0c
0049176 45 bf 00 00
0049180 00 00 00 00
0049184 00 00 00 00
</div>
</pre>
<p><span id="more-2407"></span></p>
<p>-j 49152 跳过前49152个字节（bytes）</p>
<p>-N 38 仅显示38个字节</p>
<p>-w4 每一行显示4个字节</p>
<p>-A d 表示最左侧的偏移量按十进制显示；-A还可以接[doxn]，其中d表示十进制，o表示8进制，x表示16进制，n表示不显示该偏移量，如：</p>
<pre>
<div class="mycode">od -j 49152 -N 8 -w4 -A n -t x1 -v ibdata1
 b4 0b c7 31
 00 00 00 03
</div>
</pre>
<p>-t x1表示如何显示文件内容。这里，x表示按照16进制输出文件内容，x后面跟的“1”表示一次显示一个字节。下面是一个-t x2的输出：</p>
<pre>
<div class="mycode">od -j 49152 -N 8 -w4 -A n -t x2 -v ibdata1
 0bb4 31c7    # 0bb4是十进制表示的两个字节
 0000 0300    #
</div>
</pre>
<p>另外，注意到这里是0bb4和前面的b40b略有不同，这是因为我这里的测试平台是little-endian的（x86_64 Linux）。</p>
<p>最后，参数-v表示，即使连续多行都是完全相同的字符0，仍然原样输出；不加该参数，则会使用星号（*）跳过多个相同的行。</p>
<p>好了，再回头看看最前面的命令，已经没那么难理解了吧。</p>
<p>参考文献：man od</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2010/08/linux-od-data-file/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to kill an `uninterruptible sleep` process</title>
		<link>http://www.orczhou.com/index.php/2010/05/how-to-kill-an-uninterruptible-sleep-process/</link>
		<comments>http://www.orczhou.com/index.php/2010/05/how-to-kill-an-uninterruptible-sleep-process/#comments</comments>
		<pubDate>Tue, 18 May 2010 12:49:19 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=1974</guid>
		<description><![CDATA[<p>很早之前就遇到一次这个故障，当时是一台主机故障，这次是上百台主机故障。当时是使用mysqldump向NFS备份时，写数据时大概是NFS出现故障，使得mysqldump进程进入uninterruptible sleep（man ps）状态：</p>
<div class="mycode">$ps axu&#124;grep mysqldump<br />
mysql     2718  0.0  0.0 51088  672 pts/0    S+   13:30   0:00 grep mysqldump<br />
mysql    14916  1.4  0.0     0    0 ?        D    02:03  10:03 [mysqldump]</div>
<p>进入该状态的进程，会一直等待NFS，不接受任何信号，当然也就无法被杀死（kill/fuser -k）。因为进程一直在运行队列（running queue）中，所以还会导致主机的Load上升（虽然主机并不繁忙）。如果由于这个原因被卡住的进程很多的话，主机的Load可能会<strong>看起来</strong>非常高。[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2010/05/how-to-kill-an-uninterruptible-sleep-process/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>很早之前就遇到一次这个故障，当时是一台主机故障，这次是上百台主机故障。当时是使用mysqldump向NFS备份时，写数据时大概是NFS出现故障，使得mysqldump进程进入uninterruptible sleep（man ps）状态：</p>
<div class="mycode">$ps axu|grep mysqldump<br />
mysql     2718  0.0  0.0 51088  672 pts/0    S+   13:30   0:00 grep mysqldump<br />
mysql    14916  1.4  0.0     0    0 ?        D    02:03  10:03 [mysqldump]</div>
<p>进入该状态的进程，会一直等待NFS，不接受任何信号，当然也就无法被杀死（kill/fuser -k）。因为进程一直在运行队列（running queue）中，所以还会导致主机的Load上升（虽然主机并不繁忙）。如果由于这个原因被卡住的进程很多的话，主机的Load可能会<strong>看起来</strong>非常高。<span id="more-1974"></span></p>
<p>上次出现这个问题时只有一台主机出了这个症状，当时Google后也注意到很多人有遇到了<a href="http://www.google.com/search?hl=en&#038;q=NFS+uninterruptible&#038;btnG=Search&#038;aq=f&#038;aqi=&#038;aql=&#038;oq=&#038;gs_rfai=">类似的问题</a>，并且都束手无策(<a href="http://linuxgazette.net/issue83/tag/6.html">There are some things even root can't do</a>)。Google后，再尝试找了一些Linux原理方面的介绍，依然无解。</p>
<p>解决的终极办法是重启主机（reboot），所以决定等待一段时间（之前遇到过一些僵死进程Z，等待一段时间后也消失了），实在不行就择机重启主机。不过奇怪的是，等了几天过后，这个进程确实消失了（正常结束了？应该是）。</p>
<p><font color="red">1. Why is Linux so "stupid"?</font></p>
<p>有人就问，Linux设计是不是有问题，为什么会有一些进程root也无法杀死呢？</p>
<p>jra在<a href="http://linuxgazette.net/issue83/tag/6.html">How to kill a process in uninterruptible sleep state</a>中给了一个解释：</p>
<pre>
<div class="mycode">    There's fairly extensive discussion of this in a couple of the kernel
design books, and I think in Nemeth, Snyder and Seebass: the problem stems
from the fact that there are two types of device drivers -- those
for "fast" devices and those for "slow" devices：

    Slow-device drivers -- for things like terminals, and such -- are
                usually split in two pieces, and can therefore be
                interrupted while they're in the middle of something.

    Fast-device drivers -- which service things like hard drives and (I
                think) ethernet cards -- are designed to expect that
                when they call out to hardware, it will respond  instantly
                (in human terms), and that they won't have to wait
                on anything. Such drivers have, as a rule, proven
                extremely intolerant of hardware trouble -- if your hard
                drive start having to do hardware retries to read a
                sector, your system perfromance is going int he toilet,
                even if you have more than one drive...</div>
</pre>
<p>大概意思是说，Linux中设备驱动程序可以分为“slow device”和“fast device”两类。磁盘属于“fast device”（如果当作“slow device”处理效率会很低），在这类设备上操作时会以uninterruptible的方式进行。</p>
<p><font color="red">2. 真的没办法吗?</font></p>
<p>理论上，除了重启主机，貌似没什么办法了。不过，根据实际经验和运气，也还是有一些办法可以尝试的。</p>
<p><font color="blue">办法1：umount -f</font></p>
<p>如果是由于NFS故障导致的，可以尝试使用先umount/mount重新挂载NFS。如果NFS无法卸载（如果遇到上述情况，八成是这样），可以尝试使用 -f 参数卸载。最近一次遇到这个故障，有接近上百台主机出现这个故障，就是使用umount -f成功卸载NFS后，相关uninterruptible的进程也都随之正常结束。当时发现，连续重试多次 umount -f 才行：</p>
<div class="mycode">root>#umount -f /nfsdir<br />
umount2: Device or resource busy<br />
umount: /nfsdir: device is busy<br />
root>#umount -f /nfsdir<br />
umount2: Device or resource busy<br />
umount: /nfsdir: device is busy</div>
<p><font color="blue">办法2：等</font></p>
<p>最早mysqldump遇到这个问题时，束手无策后，就等了几天，发现进程确实结束了。所以如果情况不是很紧急，“等”也是一个办法。</p>
<p>遇到的僵死进程这个办法也可能有效。</p>
<p><font color="blue">办法3：killall -KILL rpciod</font></p>
<p>在<a href="http://bbs.unixall.com/thread-441-1-1.html">一篇文章</a>中，还提到，进程处于uninterruptible sleep(即ps的D状态)，进程处于rpc_execute调用状态，而rpc_execute调用是由rpciod提供，所以可以通过杀死rpciod来解决问题。（rpciod被杀死后会自动重启过来）【没有实验过，慎用，希望有经验者分享一下】</p>
<p><font color="blue">办法4：reboot</font></p>
<p>实在不行，就只能reboot了。这是最不推荐的做法，毕竟每次遇到都reboot，代价还是比较大，特别是当你在追求HA的时候。</p>
<p><font color="red">3. 能够避免这种情况吗?</font></p>
<p>在RTFM之后，发现可以通过挂载NFS时指定一些参数，尽可能的避免这个问题：</p>
<pre>
<div class="mycode">     soft       If an NFS file operation has a major timeout then report
                 an I/O error to the calling program.  The default is  to
                 continue retrying NFS file operations indefinitely.

      hard       If an NFS file operation has a major timeout then report
                 "server not responding"  on  the  console  and  continue
                 retrying indefinitely.  This is the default.

      intr       If  an  NFS file operation has a major timeout and it is
                 hard mounted, then allow signals to  interupt  the  file
                 operation  and  cause  it to return EINTR to the calling
                 program.  The default is to not allow file operations to
                 be interrupted.</div>
</pre>
<p>上面3个参数，其中hard是默认的。我们通过断开网络模拟NFS故障，测试了 intr 选项，发现能够一定程度上避免上述的情况。在测试 soft 选项时，并没有上面描述的那么好用，在实验中，使用 soft 挂载是现象和 hard 类似（不知道我是不是忽略哪些细节了）。</p>
<p>如果你被这个问题困扰，可以试试使用intr参数挂载NFS：</p>
<div class="mycode">mount -o intr 172.23.119.25:/nfs /nfsdir</div>
<p><font color="red">参考文献</font><br />
[1]. Linux Man<br />
[2]. <a href="http://linuxgazette.net/issue83/tag/6.html">How to kill a process in uninterruptible sleep state</a><br />
[3]. <a href="http://kerneltrap.org/Linux/Killing_Tasks_On_Frozen_NFS_Mounts">Linux: Killing Tasks On Frozen NFS Mounts</a><br />
[4]. <a href="http://hychen.wuweig.org/?p=30728">How to kill a process in uninterruptible sleep state</a><br />
[5]. <a href="http://bbs.unixall.com/thread-441-1-1.html">如何杀掉由NFS造成Uninterruptible的进程</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2010/05/how-to-kill-an-uninterruptible-sleep-process/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>使用getopts处理Shell脚本参数</title>
		<link>http://www.orczhou.com/index.php/2010/04/linux-shell-getopt/</link>
		<comments>http://www.orczhou.com/index.php/2010/04/linux-shell-getopt/#comments</comments>
		<pubDate>Wed, 21 Apr 2010 11:48:21 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[技术细节]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=1822</guid>
		<description><![CDATA[<p>编写一个shell脚本，做一些事；改进这个脚本，更好做这件事；再改进这个脚本，帮自己做些其他的事情；再改进这个脚本帮助其他人做一些事......</p>
<p>简单的脚本处理，一般使用变量$0 $1 $2 ...就可以依次获得全部参数，还可以通过$#获得这个脚本一共有多少个参数。如果你需要处理的情况（或者分支）更多的时候，这个方法就不凑效了，这时候，就可以考虑使用getopts了（man getopts）。[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2010/04/linux-shell-getopt/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>编写一个shell脚本，做一些事；改进这个脚本，更好做这件事；再改进这个脚本，帮自己做些其他的事情；再改进这个脚本帮助其他人做一些事......</p>
<p>简单的脚本处理，一般使用变量$0 $1 $2 ...就可以依次获得全部参数，还可以通过$#获得这个脚本一共有多少个参数。如果你需要处理的情况（或者分支）更多的时候，这个方法就不凑效了，这时候，就可以考虑使用getopts了（man getopts）。<span id="more-1822"></span></p>
<p>这里将通过一个示例来介绍getopts的用法。</p>
<p>下面的代码，可以通过"./sample -d 5"的方式获取参数：</p>
<pre>
<div class="mycode">vi sample.sh
#!/bin/sh
day=7  #default value
while getopts ":d:" opt; do
  case $opt in
    d)
      day=$OPTARG   #get the value
      ;;
    ?)
      echo "How to use: $0 [-d DAY]" >&#038;2
      exit 1
      ;;
    &#58;)
      echo "Option -$OPTARG requires an argument." >&#038;2
      exit 1
      ;;
  esac
done
echo $day
</div>
</pre>
<p>上面例子中需要解释的是下面的部分：</p>
<pre>
<div class="mycode">while getopts ":d:" opt; do</div>
</pre>
<p>这里，第一个冒号表示忽略错误（例如出现了不认识的参数），并在脚本中通过:&#58;)来处理这样的错误；字母d则表示，接受参数-d；d后面的冒号表示参数d接收值，即“-d 7”这样的形式；（这里opt变量，可以在while循环中引用当前找到的参数，试试输出$opt试试）</p>
<p>如果是要有很多参数，那么写法可能是：</p>
<pre>
<div class="mycode">while getopts ":ixarm:uneh" opt; do</div>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2010/04/linux-shell-getopt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux iostat监测IO状态</title>
		<link>http://www.orczhou.com/index.php/2010/03/iostat-detail/</link>
		<comments>http://www.orczhou.com/index.php/2010/03/iostat-detail/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 05:13:28 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[技术细节]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=1228</guid>
		<description><![CDATA[<p>Linux系统出现了性能问题，一般我们可以通过top、iostat、free、vmstat等命令来查看初步定位问题。其中iostat可以给我们提供丰富的IO状态数据。</p>
<p><font color="red">1. 基本使用</font></p>
<pre>
<div class="mycode">$iostat -d -k 1 10</div>
</pre>
<p>参数 -d 表示，显示设备（磁盘）使用状态；-k某些使用block为单位的列强制使用Kilobytes为单位；1 10表示，数据显示每隔1秒刷新一次，共显示10次。[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2010/03/iostat-detail/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>Linux系统出现了性能问题，一般我们可以通过top、iostat、free、vmstat等命令来查看初步定位问题。其中iostat可以给我们提供丰富的IO状态数据。</p>
<p><font color="red">1. 基本使用</font></p>
<pre>
<div class="mycode">$iostat -d -k 1 10</div>
</pre>
<p>参数 -d 表示，显示设备（磁盘）使用状态；-k某些使用block为单位的列强制使用Kilobytes为单位；1 10表示，数据显示每隔1秒刷新一次，共显示10次。<span id="more-1228"></span></p>
<pre>
<div class="mycode">$iostat -d -k 1 10
Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda              39.29        21.14         1.44  441339807   29990031
sda1              0.00         0.00         0.00       1623        523
sda2              1.32         1.43         4.54   29834273   94827104
sda3              6.30         0.85        24.95   17816289  520725244
sda5              0.85         0.46         3.40    9543503   70970116
sda6              0.00         0.00         0.00        550        236
sda7              0.00         0.00         0.00        406          0
sda8              0.00         0.00         0.00        406          0
sda9              0.00         0.00         0.00        406          0
sda10            60.68        18.35        71.43  383002263 1490928140

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda             327.55      5159.18       102.04       5056        100
sda1              0.00         0.00         0.00          0          0
</div>
</pre>
<p><font color="blue">tps</font>：该设备每秒的传输次数（Indicate  the  number  of  transfers  per  second that were issued to the device.）。“一次传输”意思是“一次I/O请求”。多个逻辑请求可能会被合并为“一次I/O请求”。“一次传输”请求的大小是未知的。</p>
<p><font color="blue">kB_read/s</font>：每秒从设备（drive expressed）读取的数据量；<font color="blue">kB_wrtn/s</font>：每秒向设备（drive expressed）写入的数据量；<font color="blue">kB_read</font>：读取的总数据量；<font color="blue">kB_wrtn</font>：写入的总数量数据量；这些单位都为Kilobytes。</p>
<p>上面的例子中，我们可以看到磁盘sda以及它的各个分区的统计数据，当时统计的磁盘总TPS是39.29，下面是各个分区的TPS。（因为是瞬间值，所以总TPS并不严格等于各个分区TPS的总和）</p>
<p><font color="red">2. -x 参数</font></p>
<p>使用-x参数我们可以获得更多统计信息。</p>
<pre>
<div class="mycode">iostat -d -x -k 1 10
Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          1.56  28.31  7.80 31.49   42.51    2.92    21.26     1.46     1.16     0.03    0.79   2.62  10.28
Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          2.00  20.00 381.00  7.00 12320.00  216.00  6160.00   108.00    32.31     1.75    4.50   2.17  84.20
</div>
</pre>
<p><font color="blue">rrqm/s</font>：每秒这个设备相关的读取请求有多少被Merge了（当系统调用需要读取数据的时候，VFS将请求发到各个FS，如果FS发现不同的读取请求读取的是相同Block的数据，FS会将这个请求合并Merge）；wrqm/s：每秒这个设备相关的写入请求有多少被Merge了。</p>
<p><font color="blue">rsec/s</font>：每秒读取的扇区数；<font color="blue">wsec/</font>：每秒写入的扇区数。<font color="blue">r/s</font>：The number of read requests that were issued to the device per second；<font color="blue">w/s</font>：The number of write requests that were issued to the device per second；</p>
<p><font color="blue">await</font>：每一个IO请求的处理的平均时间（单位是<del datetime="2011-03-01T08:00:29+00:00">微秒</del>毫秒）。这里可以理解为IO的响应时间，一般地系统IO响应时间应该低于5ms，如果大于10ms就比较大了。</p>
<p><font color="blue">%util</font>：在统计时间内所有处理IO时间，除以总共统计时间。例如，如果统计间隔1秒，该设备有0.8秒在处理IO，而0.2秒闲置，那么该设备的%util = 0.8/1 = 80%，所以该参数暗示了设备的繁忙程度。一般地，如果该参数是100%表示设备已经接近满负荷运行了（当然如果是多磁盘，即使%util是100%，因为磁盘的并发能力，所以磁盘使用未必就到了瓶颈）。</p>
<p><font color="red">3. -c 参数</font></p>
<p>iostat还可以用来获取cpu部分状态值：</p>
<pre>
<div class="mycode"><strong>iostat -c 1 10</strong>
avg-cpu:  %user   %nice    %sys %iowait   %idle
           1.98    0.00    0.35   11.45   86.22
avg-cpu:  %user   %nice    %sys %iowait   %idle
           1.62    0.00    0.25   34.46   63.67</div>
</pre>
<p><font color="red">4. 常见用法</font></p>
<pre>
<div class="mycode">$iostat -d -k 1 10        #查看TPS和吞吐量信息
iostat -d -x -k 1 10      #查看设备使用率（%util）、响应时间（await）
iostat -c 1 10            #查看cpu状态
</div>
</pre>
<p><font color="red">5. 实例分析</font></p>
<pre>
<div class="mycode">$$iostat -d -k 1 |grep sda10
Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda10            60.72        18.95        71.53  395637647 1493241908
sda10           299.02      4266.67       129.41       4352        132
sda10           483.84      4589.90      4117.17       4544       4076
sda10           218.00      3360.00       100.00       3360        100
sda10           546.00      8784.00       124.00       8784        124
sda10           827.00     13232.00       136.00      13232        136</div>
</pre>
<p>上面看到，磁盘每秒传输次数平均约400；每秒磁盘读取约5MB，写入约1MB。</p>
<pre>
<div class="mycode">iostat -d -x -k 1
Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          1.56  28.31  7.84 31.50   43.65    3.16    21.82     1.58     1.19     0.03    0.80   2.61  10.29
sda          1.98  24.75 419.80  6.93 13465.35  253.47  6732.67   126.73    32.15     2.00    4.70   2.00  85.25
sda          3.06  41.84 444.90 54.08 14204.08 2048.98  7102.04  1024.49    32.57     2.10    4.21   1.85  92.24</div>
</pre>
<p>可以看到磁盘的平均响应时间<5ms，磁盘使用率>80。磁盘响应正常，但是已经很繁忙了。</p>
<p>参考文献：</p>
<ol>
<li>Linux man iostat</li>
<li><a href="http://www.xaprb.com/blog/2010/01/09/how-linux-iostat-computes-its-results/">How Linux iostat computes its results</a></li>
<li><a href="http://www.mjmwired.net/kernel/Documentation/iostats.txt">Linux iostat</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2010/03/iostat-detail/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Linux本地磁盘（硬盘）介绍</title>
		<link>http://www.orczhou.com/index.php/2010/02/linux-disk-hardware/</link>
		<comments>http://www.orczhou.com/index.php/2010/02/linux-disk-hardware/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 12:05:27 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[技术细节]]></category>

		<guid isPermaLink="false">http://www.orczhou.com/?p=1243</guid>
		<description><![CDATA[<p>本文试图从硬件结构、逻辑结构两方面来介绍Linux中本地磁盘的基本知识。</p>
<p><font color="red">1. 硬件结构</font></p>
<p>一块磁盘由多个盘面组成，每个盘面有一个对应的<strong>磁头（heads）</strong>，我们可以在该盘面上存储我们需要的信息。</p>
<p>每一个盘面，被分成多个圆环，我们称之为<strong>柱面（cylinders）</strong>。每一个柱面又被分割为多个扇形区域，简称<strong>扇区（sectors）</strong>，参见下图：</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/4381155033/" title="磁盘扇区 by orczhou, on Flickr"><img src="http://farm3.static.flickr.com/2725/4381155033_048953a69d_o.png" width="392" height="275" alt="磁盘扇区" /></a>（图片来源<a href="http://www.eygle.com/">www.eygle.com/</a>）</p>
<p>两个红色环形之间是一个柱面；图中黄色标记部分是一个扇区。[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2010/02/linux-disk-hardware/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>本文试图从硬件结构、逻辑结构两方面来介绍Linux中本地磁盘的基本知识。</p>
<p><font color="red">1. 硬件结构</font></p>
<p>一块磁盘由多个盘面组成，每个盘面有一个对应的<strong>磁头（heads）</strong>，我们可以在该盘面上存储我们需要的信息。</p>
<p>每一个盘面，被分成多个圆环，我们称之为<strong>柱面（cylinders）</strong>。每一个柱面又被分割为多个扇形区域，简称<strong>扇区（sectors）</strong>，参见下图：</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/4381155033/" title="磁盘扇区 by orczhou, on Flickr"><img src="http://farm3.static.flickr.com/2725/4381155033_048953a69d_o.png" width="392" height="275" alt="磁盘扇区" /></a>（图片来源<a href="http://www.eygle.com/">www.eygle.com/</a>）</p>
<p>两个红色环形之间是一个柱面；图中黄色标记部分是一个扇区。<span id="more-1243"></span></p>
<p><font color="red">2. fdisk -l 查看磁盘情况</font></p>
<pre>
<div class="mycode">#fdisk -l
Disk /dev/sda: 73.2 GB, 73274490880 bytes
255 heads, 63 sectors/track, 8908 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          16      128488+  83  Linux
/dev/sda2              17        1928    15358140   83  Linux
/dev/sda3            1929        2189     2096482+  82  Linux swap / Solaris
/dev/sda4            2190        8908    53970367+   5  Extended
/dev/sda5            2190        2450     2096451   82  Linux swap / Solaris
/dev/sda6            2451        2711     2096451   82  Linux swap / Solaris
/dev/sda7            2712        2972     2096451   82  Linux swap / Solaris
/dev/sda8            2973        8908    47680888+  83  Linux
</div>
</pre>
<p>可以看到，上面的磁盘/dev/sda有255个磁头，8908个柱面，每个柱面轨道上有63个扇区。因为每个扇区大小为512bytes，所以总大小约为：8908 * 63 * 512 * 255 = 73270794240(和上面的73274490880 相差3696640，不知道是什么地方多出来的)。</p>
<p><font color="red">3. 磁盘分区、文件系统、挂载点</font></p>
<p>我们继续看上面的例子，磁盘/dev/sda共分为8个分区：/dev/sda1，/dev/sda2，......，/dev/sda8，Start和End分别为各个分区的起始和结束柱面。例如分区/dev/sda2从柱面17开始到柱面1928结束，则大小约为（1928-17）* 63 * 512 * 255 = 14.6G。</p>
<p>可以通过df -h来查看分区/dev/sda2的挂载目录：</p>
<pre>
<div class="mycode">#df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda2              15G   13G  1.1G  92% /
/dev/sda1             122M   20M   96M  17% /boot
tmpfs                 2.0G  669M  1.4G  33% /dev/shm
/dev/sda8              45G   26G   17G  62% /u01
</div>
</pre>
<p>可以看到，分区/dev/sda2挂载根目录 / 上。然后，通过文件/etc/fstab来查看该分区的文件系统：</p>
<pre>
<div class="mycode">#more /etc/fstab
LABEL=/                 /                       ext3    defaults        1 1
LABEL=/boot1            /boot                   ext3    defaults        1 2
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
tmpfs                   /dev/shm                tmpfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
sysfs                   /sys                    sysfs   defaults        0 0
LABEL=/u01              /u01                    ext3    defaults        1 2
LABEL=SWAP-sda5         swap                    swap    defaults        0 0
LABEL=SWAP-sda6         swap                    swap    defaults        0 0
LABEL=SWAP-sda7         swap                    swap    defaults        0 0
LABEL=SWAP-sda3         swap                    swap    defaults        0 0
</div>
</pre>
<p>看到根目录 / 使用了Linux ext3文件系统。</p>
<p>至此，我们看到磁盘/dev/sda共分为八个分区。其中第二个分区/dev/sda2从柱面17到柱面1928结束，大小约为15G，该分区挂载在根目录 / 上，使用了ext3的文件系统。</p>
<p><font color="red">4. 其他磁盘分区</font></p>
<p>在上面的fdisk -l 列表中我们一共可以看到八个磁盘分区。上面已经分析了/dev/sda2，我们再看来看看其他的分区。</p>
<ul>
<li>在Linux中第一个分区/dev/sda1，为引导扇区，挂载在/boot上</li>
<li>第二个分区挂载在根目录 / 上，大小15G，为ext3文件系统</li>
<li>第三个分区为交换分区，从柱面1929到2189，大小约：（2189 - 1929）* 63 * 512 * 255 = 2G。</li>
<li>第四个分区为扩展分区，后面四个分区均是该分区的一部分。该分区从柱面2190到8908结束。</li>
<li>分区五、六、七为扩展分区的子分区，均为交换分区，单个大小均为2G。所以全部的交换分区大小共2G + 2G*3 = 8G。</li>
<li>第八个分区为扩展分区的最后一个子分区，挂载在/u01上，大小约为 （8908 - 2973）* 63 * 512 * 255 = 45G。</li>
</ul>
<p>以上为示例主机上的全部磁盘分区，以及挂载情况。</p>
<p><font color="red">5. 小结</font></p>
<p>有了以上信息，我们就基本清楚了硬件结构以及对应的逻辑结构，需要使用的命令其实也很少：</p>
<div class="mycode">
#fdisk -l<br />
#df -h<br />
#more /etc/fstab
</div>
<p><font color="red">6. 补充</font></p>
<pre>
<div class="mycode"># This file is edited by fstab-sync - see 'man fstab-sync' for details
LABEL=/1                /                       ext3    defaults        1 1
LABEL=/boot1            /boot                   ext3    defaults        1 2
......
</div>
</pre>
<p>关于/etc/fstab的简单补充：</p>
<ul>
<li>第一列是：一般是设备（分区），如也有是LABEL=×××的，这是ext2 ext3特有的卷标，可以通过e2label来查看各个设备的卷标。</li>
<li>第二列是：挂载点</li>
<li>第三列是：文件系统</li>
<li>第四列是：文件系统挂载时候的参数（例如NFS有时候需要用户名密码等）</li>
<li>第五列是：标志是否需要备份1为需要，0为不需要</li>
<li>第六列是：启动时，是否需要fsck检查磁盘1为先检查，2为后检查，0为不检查</li>
</ul>
<p>在fstab文件还有部分第一列是none的，这些都是不需要物理磁盘的文件系统。典型的如/proc文件系统：</p>
<pre>
<div class="mycode">none                    /dev/shm                tmpfs   defaults        0 0
none                    /proc                   proc    defaults        0 0
none                    /sys                    sysfs   defaults        0 0
</div>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2010/02/linux-disk-hardware/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>mysqld随Linux开机自动启动</title>
		<link>http://www.orczhou.com/index.php/2009/11/mysqldauto/</link>
		<comments>http://www.orczhou.com/index.php/2009/11/mysqldauto/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 03:11:41 +0000</pubDate>
		<dc:creator>orczhou</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[技术细节]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://orczhou.com/?p=1004</guid>
		<description><![CDATA[<p>在MySQL的管理过程中，偶尔会遇到一些PC Server宕机或者重启，这时我需要在主机启动后再将MySQL服务启动。一般情况下，这项工作都是简单的。但是，当面临上百台或者更多的MySQL主机的时候，这种“偶尔”可能会很多，这种“偶尔”还会在半夜或者凌晨发生，如果每次都手动操作，这是很繁琐的。更重要的是，如果因此而打断了凌晨的美梦是不值得的。</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/4132795867/" title="LinuxMySQL-2 by orczhou, on Flickr"><img src="http://farm3.static.flickr.com/2660/4132795867_0e8c895ca4_o.png" width="341" height="268" alt="LinuxMySQL-2" /></a></p>
<p>[......]</p><p class='read-more'><a href='http://www.orczhou.com/index.php/2009/11/mysqldauto/'>继续阅读</a></p>]]></description>
			<content:encoded><![CDATA[<p>在MySQL的管理过程中，偶尔会遇到一些PC Server宕机或者重启，这时我需要在主机启动后再将MySQL服务启动。一般情况下，这项工作都是简单的。但是，当面临上百台或者更多的MySQL主机的时候，这种“偶尔”可能会很多，这种“偶尔”还会在半夜或者凌晨发生，如果每次都手动操作，这是很繁琐的。更重要的是，如果因此而打断了凌晨的美梦是不值得的。</p>
<p><a href="http://www.flickr.com/photos/26825745@N06/4132795867/" title="LinuxMySQL-2 by orczhou, on Flickr"><img src="http://farm3.static.flickr.com/2660/4132795867_0e8c895ca4_o.png" width="341" height="268" alt="LinuxMySQL-2" /></a></p>
<p><span id="more-1004"></span></p>
<p>要实现随开启自动启动mysqld，我们需要搞定如下几个问题：</p>
<p><font color="red">1. Linux开机自动启动脚本放在哪儿？</font> </p>
<p>一般的，作为服务器使用的Linux一般会以“完全多用户模式(Multi-User Mode with Networking)”级别来启动，这种情况下Linux在启动时会运行/etc/rc.d/rc3.d/下的全部脚本。例如我们在这个目录下会看到脚本"/etc/rc.d/rc3.d/S90crond"，意味着开机启动时会运行S90crond脚本。</p>
<p><font color="red">2. Linux如何运行这些脚本？</font> </p>
<p>既然已经知道自动启动脚本该放在哪儿了，一切就好办。我们只需要将一个启动MySQL的脚本放过去就好了。下面是我们的一个简单的启动脚本v0.1 mysqldauto</p>
<div class="mycode">
$vi mysqldauto<br />
#!/bin/sh<br />
# Version: 0.1 by orczhou@gmail.com<br />
/opt/mysql/bin/mysqld_safe --user=mysql &#038;      #这里需要修改为你的mysqld_safe目录<br />
$chmod +x mysqldauto<br />
$mv mysqldauto /etc/rc.d/init.d/<br />
$ln -s /etc/rc.d/init.d/mysqldauto /etc/rc.d/rc3.d/S99mysqld
</div>
<p>这样我们就把创建的mysqldauto脚本放到了/etc/rc.d/rc3.d/下面（注意这里使用了link的方式），mysqld可以自动启动了。</p>
<p>这有两个问题需要解释：</p>
<p>* <font color="red"> * </font>* <font color="red">*</font> * 为什么不直接在目录/etc/rc.d/rc3.d/下创建文件，而要创建一个软连接？这并不是必须的。但是这样做是有很多好处的（后面会解释），不过这样做至少会看起来更加专业。</p>
<p>* <font color="red"> * </font>* <font color="red">*</font> * 为什么文件名要用S99mysqld？这是规则，在rc3.d下面的脚本如果以字母S开头，那么执行时Linux会给它传递一个start参数（如果以字母K开头，则会传递stop参数）；S后面接个数字，表示了这个脚本的启动顺序，如果目录rc3.d下还有S98*那么它会在S99之前运行。（看到这儿，你可以猜测一下前面我们为什么要创建软连接了）</p>
<p>好了，自此你的mysqld就已经可以随Linux开机自动启动了。</p>
<p><font color="red">3. 怎样做更专业些？</font> </p>
<p>上面这样做，已经可以解决问题了，不过写法多少有些“山寨”，下面我们看看怎样改造一下。</p>
<p>* <font color="red"> * </font>* <font color="red">*</font> * 改造1：处理参数start。既然前面提到以字母S开头的脚本会自动传递一个参数start，K则会传递stop。那么我再做如下修改：</p>
<pre>
<div class="mycode">
$vi mysqldauto
#!/bin/sh
# Version: 0.2 by orczhou@gmail.com
MYSQLHOME=/opt/mysql                         #这里需要修改为你的mysql安装目录
if [ $# -ge 1 ];then
        mysqldProc=`ps -ef|grep -E "mysqld.+safe"|grep -v "grep"|wc -l`
        if [ $1 = "stop" ] ;then
                if [ $mysqldProc -eq 1 ];then
                        $MYSQLHOME/bin/mysqladmin -uroot shutdown
	fi
        elif [ $1 = "start" ];then
                if [ $mysqldProc -eq 0 ];then
                        $MYSQLHOME/bin/mysqld_safe --user=mysql &#038;
	        fi
        fi
fi
</div>
</pre>
<p>做了如此改造后，我们脚本需要接收两个参数start stop了。如果你想让你mysqld在关闭主机的时候自动关闭，那么stop参数就可以起作用了：</p>
<div class="mycode">
$ln -s /etc/rc.d/init.d/mysqldauto /etc/rc.d/rc0.d/K20mysqld
</div>
<p>这里做软连接好处就体现出来了，启动和关闭只需要用一个脚本就可以了。</p>
<p>* <font color="red"> * </font>* <font color="red">*</font> * 改造2：当你面临几十上百台主机的时候，MySQL的启动参数可能会不一样，例如备库启动时可能需要mysqld_safe --user=mysql --read_olny=1 &#038;，这种情况怎么办呢？这里提供一个解决思路。</p>
<p>在主机上运行一个脚本，探测当前mysqld的启动参数，然后写到一个指定的文件里。最后，在你的启动脚本中，读取这个文件里面的启动参数来启动mysqld。It works。</p>
<p>最后，祝你睡个好觉，做个好梦。</p>
<p>（全文完）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orczhou.com/index.php/2009/11/mysqldauto/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

