<?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>Tim[后端技术] &#187; data</title>
	<atom:link href="http://timyang.net/category/data/feed/" rel="self" type="application/rss+xml" />
	<link>http://timyang.net</link>
	<description>Tim&#039;s blog, 关于后端架构、互联网技术、分布式、大型网络应用、NoSQL、Key Value等</description>
	<lastBuildDate>Mon, 26 Jul 2010 15:32:05 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Twitter停用Cassandra原因分析</title>
		<link>http://timyang.net/data/twitter-cassandra/</link>
		<comments>http://timyang.net/data/twitter-cassandra/#comments</comments>
		<pubDate>Sun, 11 Jul 2010 16:29:41 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[data]]></category>
		<category><![CDATA[cassandra]]></category>
		<category><![CDATA[key value store]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=623</guid>
		<description><![CDATA[Twitter在其7.9一篇官方技术博客Cassandra at Twitter Today提到暂停使用Cassandra来代替MySQL存储feed的计划，这是Twitter一个重要的架构策略调整，因为之前Twitter一直是业界Cassandra方向的领头羊。
For now, we&#8217;re not working on using Cassandra as a store for Tweets. This is a change in strategy. Instead we&#8217;re going to continue to maintain our existing Mysql-based storage. We believe that this isn&#8217;t the time to make large scale migration to a new technology. We will focus our Cassandra work [...]]]></description>
			<content:encoded><![CDATA[<p>Twitter在其7.9一篇官方技术博客<a href="http://engineering.twitter.com/2010/07/cassandra-at-twitter-today.html">Cassandra at Twitter Today</a>提到暂停使用Cassandra来代替MySQL存储feed的计划，这是Twitter一个重要的架构策略调整，因为之前Twitter一直是业界Cassandra方向的领头羊。</p>
<blockquote><p>For now, we&#8217;re not working on using Cassandra as a store for Tweets. This is a change in strategy. Instead we&#8217;re going to continue to maintain our existing Mysql-based storage. We believe that this isn&#8217;t the time to make large scale migration to a new technology. We will focus our Cassandra work on new projects that we wouldn&#8217;t be able to ship without a large-scale data store.</p></blockquote>
<h3>Twitter为什么要停用Cassandra</h3>
<p>我们来分析一下Twitter停止使用Cassandra的原因<br />
1. Cassandra仍然缺少大并发海量数据访问的案例及经验，Cassandra来源自Facebook，但是在Facebook内部Cassandra目前只用在inbox search产品上，容量大约有100-200T。且Inbox Search在Facebook的基础架构中也并非核心应用。并且还传出不少rumors说facebook已经放弃Cassandra。</p>
<p>2. 新产品需要一定稳定期，Cassandra代码或许还存在不少问题，但是Twitter如果投入大量的精力来改进Cassandra和比较优化MySQL的投入来看有点得不偿失。在QCon Beijing上@<a href="http://twitter.com/nk">nk</a>也提到Cassandra在Twitter的内部测试中曾经暴露出不少严重的问题。</p>
<h3>Twitter为什么之前选用Cassandra</h3>
<p>此问题曾经在QCon Beijing 2010做过介绍，在去年的第一期广州技术沙龙也有过交流，类似Twitter这样的网站使用Cassandra的主要原因有<br />
1. 数据增长规模需要不断增加新服务器，传统的切分方案在面临增删硬件时候需要手工维护，当数据规模速度增快，业务又不运行停机维护，手工维护的成本增加造成系统运维不堪重负。<br />
2. 不能简单增加服务器解决请求量增长的问题，需要数据架构师精细的规划。<br />
3. 每一个新的特性都需要重复评估数据拆分及访问优化的问题，架构师需要投入大量精力review几乎相同的业务场景。</p>
<p>Twitter的调整对于MySQL业界来说或许是一大利好，MySQL虽然受近期Oracle收购阴影的影响，但是对于目前大多数拥有海量数据访问的网站依然是他们第一选择。MySQL简单，可靠，安全，配套工具完善，运维成熟。业界碰到的大部分可扩展性方面的问题在MySQL中其实都有清晰明确的解决方法。虽然重复sharding的问题很烦，增删机器相关的运维工作也很繁琐，但是这些工作量还是在可以接受的范围内。</p>
<p>究竟Twitter这次策略改变是NoSQL运动的一次挫折还是前进中的一段小插曲？我们拭目以待。目前另外一大Web 2.0巨头Digg仍然在使用Cassandra。</p>
Similar Posts:<ul><li><a href="http://timyang.net/architecture/2010-tech-predictions/" rel="bookmark" title="December 31, 2009">2010年的技术架构建议</a></li>

<li><a href="http://timyang.net/sns/web20-forum/" rel="bookmark" title="June 6, 2010">Web 2.0技术沙龙设想</a></li>

<li><a href="http://timyang.net/sns/facebook-f8-0/" rel="bookmark" title="July 1, 2009">Facebook平台设计(二)</a></li>

<li><a href="http://timyang.net/architecture/twitter-cache-architecture/" rel="bookmark" title="October 28, 2009">Twitter架构图(cache篇)</a></li>

<li><a href="http://timyang.net/architecture/farmville/" rel="bookmark" title="March 8, 2010">FarmVille(美版开心农场)谈架构:所有模块都是一个可降级的服务</a></li>
</ul><!-- Similar Posts took 54.252 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/data/twitter-cassandra/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>多IDC的数据分布设计(二)</title>
		<link>http://timyang.net/data/multi-idc-design/</link>
		<comments>http://timyang.net/data/multi-idc-design/#comments</comments>
		<pubDate>Wed, 24 Mar 2010 18:18:48 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[data]]></category>
		<category><![CDATA[consensus]]></category>
		<category><![CDATA[dynamo]]></category>
		<category><![CDATA[paxos]]></category>
		<category><![CDATA[PNUTS]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=586</guid>
		<description><![CDATA[在前文《多IDC的数据分布设计(一)》中介绍了多IDC数据一致性的几种实现原理，遗憾的是，目前虽然有不少分布式产品，但几乎都没有开源的产品专门针对IDC来优化。本文从实践的角度分析各种方法优缺点。
背景资料 Latency差异
Jeff Dean提到不同数据访问方式latency差异
Numbers Everyone Should Know
L1 cache reference                           0.5 ns
Branch mispredict                            5 ns
L2 cache reference                           7 ns
Mutex lock/unlock                           25 ns
Main memory reference                      100 ns
Compress 1K bytes with Zippy             3,000 ns
Send 2K bytes over 1 Gbps network       20,000 ns
Read 1 MB sequentially from memory     250,000 ns
Round trip within same datacenter      500,000 ns
Disk seek                           10,000,000 ns
Read 1 [...]]]></description>
			<content:encoded><![CDATA[<p>在前文《<a href="http://timyang.net/distributed/multi-idc-consensus/">多IDC的数据分布设计(一)</a>》中介绍了多IDC数据一致性的几种实现原理，遗憾的是，目前虽然有不少分布式产品，但几乎都没有开源的产品专门针对IDC来优化。本文从实践的角度分析各种方法优缺点。</p>
<h3>背景资料 Latency差异</h3>
<p>Jeff Dean提到不同数据访问方式latency差异</p>
<pre>Numbers Everyone Should Know
L1 cache reference                           0.5 ns
Branch mispredict                            5 ns
L2 cache reference                           7 ns
Mutex lock/unlock                           25 ns
Main memory reference                      100 ns
Compress 1K bytes with Zippy             3,000 ns
Send 2K bytes over 1 Gbps network       20,000 ns
Read 1 MB sequentially from memory     250,000 ns
Round trip within same datacenter      500,000 ns
Disk seek                           10,000,000 ns
Read 1 MB sequentially from disk    20,000,000 ns
Send packet CA-&gt;Netherlands-&gt;CA    150,000,000 ns</pre>
<p>这个数据对于我们设计多IDC数据访问策略具有关键的指导作用，我们可以用这个数据来衡量数据架构来如何设计才能满足高并发低延迟的目标。<br />
这份数据实际上对所有网络应用及分布式应用开发者都具有很大借鉴作用，<strong>数据需要根据访问频率尽量放在latency小的地方</strong>。</p>
<h3>1. 2PC/3PC/Paxos模式</h3>
<p>在上文中提到，2PC/3PC相比Paxos有明显的缺点，因此最好不用于生产环境，这里就不再详述。<br />
Paxos选择了CAP理论中的&#8221;Consistency, Partition&#8221;, 需要牺牲availability。它可以在多个IDC之间实现强一致性复制。</p>
<p><strong>Paxos缺点</strong></p>
<ul>
<li>IDC之间需要高速稳定网络</li>
<li>一个2f+1个节点的网络中，需要f+1个节点完成事务才能成功。</li>
<li>Throughput低，不适合高请求量的场合。所以大部分分布式存储产品并不直接使用Paxos算法来同步数据。</li>
</ul>
<h3>2. Dynamo模式</h3>
<p>Dynamo论文中并未专门描述Dynamo算法是否适合多IDC场景，只有少量文字提到</p>
<blockquote><p>In essence, the preference list of a key is constructed such that the storage nodes are spread across multiple data centers. These datacenters are connected through high speed network links. This scheme of replicating across multiple datacenters allows us to handle entire data center failures without a data outage.</p></blockquote>
<p>从上文看到，前提条件是“high speed network links” 可能对国内的情况不太适用。假如IDC之间网络不稳定，那会发生哪些情况呢？</p>
<p>Quorum 算法中，如果要考虑高可用性，则数据需要分布在多个机房。双机房如NRW=322由于单机房故障后可能会发生3个点中2个点都在故障机房，导致出现数据不 可用的情况，所以合适的部署是NRW=533，需要3个机房。大部分请求需要2个机房节点返回才能成功，考虑到多IDC的带宽及latency，性能自然会很差。</p>
<p>Quorum算法在读写的时候都要从quorum中选取一个coordinator，算法如下</p>
<blockquote><p>A node handling a read or write operation is known as the<br />
coordinator. Typically, this is the first among the top N nodes in<br />
the preference list. If the requests are received through a load<br />
balancer, requests to access a key may be routed to any random<br />
node in the ring. In this scenario, the node that receives the<br />
request will not coordinate it if the node is not in the top N of the<br />
requested key’s preference list. Instead, that node will forward the<br />
request to the first among the top N nodes in the preference list.</p></blockquote>
<p>如果严格按照Dynamo协议，coodinator一定要在N中第一个节点，那在3个机房中将有2/3的请求需要forward到异地机房的 coordinator执行，导致latency增大。如果对coodinator选择做优化，让client选取preference list中前N个节点中在本地机房的一个节点作为coordinator，这样会一定程度降低latency，但是会存在相同的key选择不同节点作为 coordinator的概率增大，导致数据conflict的概率增大。</p>
<p>同时在多机房模式下，Failure detection容易产生混乱。Dynamo并没有使用一致性的failure view来判断节点失效。而是由每个节点独自判断。</p>
<blockquote><p>Failure detection in Dynamo is used to avoid attempts to<br />
communicate with unreachable peers during get() and put()<br />
operations and when transferring partitions and hinted replicas.<br />
For the purpose of avoiding failed attempts at communication, a<br />
purely local notion of failure detection is entirely sufficient: node<br />
A may consider node B failed if node B does not respond to node<br />
A’s messages (even if B is responsive to node C&#8217;s messages).</p></blockquote>
<p>而最近非常流行的Cassandra基本上可以看作是开源的Dynamo clone, 它在Facebook Inbox Search项目中部署在150台节点上，并且分布在美国东西海岸的数据中心。</p>
<blockquote><p>The system(Facebook Inbox Search) currently stores about 50+TB of data on a 150 node cluster, which is spread out between east and west coast data centers.</p></blockquote>
<p>虽然在它的JIRA中有一个提案 <a href="https://issues.apache.org/jira/browse/CASSANDRA-492">CASSANDRA-492</a> 是讲&#8221;Data Center Quorum&#8221;，但是整体看来Cassandra并没有特别的针对对IDC的优化，它的paper[5]中提到</p>
<blockquote><p>Data center failures happen due to power outages, cooling<br />
failures, network failures, and natural disasters. Cassandra<br />
is configured such that each row is replicated across multiple<br />
data centers. In essence, the preference list of a key is con-<br />
structed such that the storage nodes are spread across mul-<br />
tiple datacenters. These datacenters are connected through<br />
high speed network links. This scheme of replicating across<br />
multiple datacenters allows us to handle entire data center<br />
failures without any outage.</p></blockquote>
<p>跟Dynamo中的描述几乎是相同的。</p>
<h3>3. PNUTS模式</h3>
<p>PNUTS模式是目前最看好的多IDC数据同步方式。它的算法大部分是为多IDC设计。</p>
<p>PNUTS主要为Web应用设计，而不是离线数据分析（相比于Hadoop/HBase）。</p>
<ul>
<li>Yahoo!的数据基本都是用户相关数据，典型的以用户的username为key的key value数据。</li>
<li>统计数据访问的特征发现85%的用户修改数据经常来源自相同的IDC。</li>
</ul>
<p>根据以上的数据特征，Yahoo!的PNUTS实现算法是</p>
<ul>
<li> 记录级别的master, 每一条记录选择一个IDC作为master，所有修改都需要通过master进行。即使同一个表(tablet)中不同的记录master不同。</li>
<li>master上的数据通过Yahoo! Message Broker(YMB)异步消息将数据复制到其他IDC。</li>
<li>master选择具有灵活的策略，可以根据最新修改的来源动态变更master IDC， 比如一个IDC收到用户修改请求，但是master不在本地需要转发到远程master修改，当远程修改超过3次则将本地的IDC设成master。</li>
<li>每条记录每次修改都有一个版本号(per-record timeline consisitency)，master及YMB可以保证复制时候的顺序。</li>
</ul>
<p>Yahoo!的PNUTS实际可理解为master-master模式。<br />
<strong> 一致性</strong>：由于记录都需通过master修改，master再复制到其他IDC, 因此可达到所有IDC数据具有最终一致性。<br />
<strong> 可用性</strong>：</p>
<ul>
<li> 由于所有IDC都有每条记录的本地数据，应用可以根据策略返回本地cache或最新版本。</li>
<li>本地修改只要commit到YMB即可认为修改成功。</li>
<li>任一IDC发生故障不影响访问。</li>
</ul>
<p>论文中提到的其他优点</p>
<blockquote><p>hosted, notifications, flexible schemas, ordered records, secondary indexes, lowish latency, strong consistency on a single record, scalability, high write rates, reliability, and range queries over a small set of records.</p></blockquote>
<p>总之，PNUTS可以很好的适合geographic replication模式。</p>
<ul>
<li> 记录publish到本地YMB则认为成功，免除Dynamo方式需要等待多个Data Center返回的latency。</li>
<li>如果发生master在异地则需要将请求forward到异地，但是由于存在master转移的策略，需要forward的情况比较少。</li>
</ul>
<p>极端情况，当record的master不可用时候，实现上似乎有些可疑之处，读者可自行思考。</p>
<blockquote><p>Under normal operation, if the master copy of a record fails, our system has protocols to fail over to another replica. However, if there are major outages, e.g. the entire region that had the master copy for a record becomes unreachable, updates cannot continue at another replica without potentially violating record-timeline consistency. We will allow applications to indicate, per-table, whether they want updates to continue in the presence of major outages, potentially branching the record timeline. If so, we will provide automatic conflict resolution and notifications thereof. The application will also be able to choose from several conflict resolution policies: e.g., discarding one branch, or merging updates from branches, etc.</p></blockquote>
<h3>初步结论</h3>
<p><strong>低带宽网络</strong><br />
PNUTS record-level mastering模式最佳。<br />
<strong> 高带宽低延迟网络</strong><br />
(1Gbps, Latency &lt; 50ms)<br />
1. 用Dynamo Quorum, vector clock算法实现最终一致性<br />
2. 用Paxos实现强一致性</p>
<h3>后记</h3>
<p>本文从开始准备到发布时间较长，由于在多IDC数据访问方面目前业界并无统一的成熟方案，相关资料和文献也相对较少，而且对这方面有兴趣且有相应环境的人不多，短时间要提出自己成熟独立的见解也具有一定难度，本文仅包含一些不成熟的想法的整理，由于自己对文中的观点深度也不是满意，所以一直没有最终完稿发布。但考虑到最近工作较忙，暂时没有精力继续深入研究，所以希望公开文章抛砖引玉，同时也欢迎对这方面课题有兴趣者进一步交流探讨。</p>
<h3>Resource</h3>
<ol>
<li><a href="http://snarfed.org/space/transactions_across_datacenters_io.html">Ryan Barrett, Transactions Across Datacenters</a></li>
<li><a href="http://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf">Jeff Dean, Designs, Lessons and Advice from Building Large Distributed Systems</a> (PDF)</li>
<li><a href="http://research.yahoo.com/files/pnuts.pdf">PNUTS: Yahoo!’s Hosted Data Serving Platform</a> (PDF)</li>
<li><a href="http://bytepawn.com/2009/02/15/thoughts-on-yahoos-pnuts-distributed-database/">Thoughts on Yahoo&#8217;s PNUTS distributed database</a></li>
<li><a href="http://www.cs.cornell.edu/projects/ladis2009/papers/lakshman-ladis2009.pdf">Cassandra &#8211; A Decentralized Structured Storage System</a> (PDF)</li>
<li><a href="http://timyang.net/architecture/yahoo-pnuts/">Yahoo!的分布式数据平台PNUTS简介及感悟</a></li>
</ol>
Similar Posts:<ul><li><a href="http://timyang.net/tech/key-value-store-draft/" rel="bookmark" title="July 27, 2009">分布式key/value store演讲草稿(一)</a></li>

<li><a href="http://timyang.net/distributed/multi-idc-consensus/" rel="bookmark" title="February 2, 2010">多IDC的数据分布设计(一)</a></li>

<li><a href="http://timyang.net/architecture/yahoo-pnuts/" rel="bookmark" title="June 21, 2009">Yahoo!的分布式数据平台PNUTS简介及感悟</a></li>

<li><a href="http://timyang.net/data/dynamo-flawed-architecture-chinese/" rel="bookmark" title="March 1, 2010">Dynamo一个缺陷的架构设计(译)</a></li>

<li><a href="http://timyang.net/distributed/paxos-scenarios/" rel="bookmark" title="September 23, 2009">Paxos在大型系统中常见的应用场景</a></li>
</ul><!-- Similar Posts took 104.368 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/data/multi-idc-design/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Dynamo一个缺陷的架构设计(译)</title>
		<link>http://timyang.net/data/dynamo-flawed-architecture-chinese/</link>
		<comments>http://timyang.net/data/dynamo-flawed-architecture-chinese/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 13:46:14 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[data]]></category>
		<category><![CDATA[dynamo]]></category>
		<category><![CDATA[key value store]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=557</guid>
		<description><![CDATA[在云计算的时代，Dynamo可以说是一本实现分布式存储的红宝书，借鉴Dynamo实现的产品如雨后春笋般冒出。前段时间本人曾在Twitter上戏称
这年头，如果一个号称有“海量数据”的互联网公司，不做一个自己的Dynamo, 出去都不好意思跟人打招呼
(http://twitter.com/xmpp/status/8023241449)
另外一方面对于Dynamo设计思想也有不少反对的声音，比如2009/11/1在Hacker News上链接的一篇文章Dynamo: A flawed architecture引起不少争议，最后竟引起Amazon CTO Werner Vogels在Twitter上回应
Darn, someone figured out that Dynamo is a flawed architecture. Luckily its only use is storing hundreds of millions of shopping carts 
(http://twitter.com/Werner/statuses/5345892061)
汗，有人发现Dynamo是一个缺陷的架构，幸运的是，我们只用它来存储了成百上亿的购物篮数据。:-)
以下是这篇批判Dynamo文章大部分中心观点，所翻译的观点并不代表Tim立场。
&#8211;译文开始&#8211;
Dynamo: A flawed architecture 
在发表此文章之前，我也争论过Dynamo是否适合我们的系统。但是我很清楚这篇论文充满缺陷，它将错误的引导了读者让大家相信其设计，它的很多设计前后自相矛盾。下文会详细介绍这些缺陷。
Dynamo的最终一致性
首先，最终一致性对开发者意味什么呢？

写入的数据不能在后续的读操作中获取到。
写入的数据也有可能在后续的读操作中获取到，但读到后可能下一次又读不到。
因此对写操作后面的读取没有SLA(Service Level Agreement)保证。

举例说明，由于Dynamo是一个key value存储，我们假设value中存储的是一个list, 当list写入数据之后另外一个client却未读取到，这时候它需要写入数据的话只能重新构建一个新的list，添加要存的值并将新list存入，这就会导致老的list数据丢失。
(Update: 论坛上一些人指出，由于Vector Clock机制，数据丢失的场景不可能出现，我同意，不过我再提出几个其他问题。)

Cassandra未用vector clock, 而只用client timestamps也达到了同样效果。
Dynamo依赖合并冲突来解决此问题，一些场合下冲突很难解决。比如从list中错误的截取操作。(if deletion from the list is a valid operation &#8211; then how [...]]]></description>
			<content:encoded><![CDATA[<p>在云计算的时代，Dynamo可以说是一本实现分布式存储的红宝书，借鉴Dynamo实现的产品如雨后春笋般冒出。前段时间本人曾在Twitter上戏称</p>
<blockquote><p>这年头，如果一个号称有“海量数据”的互联网公司，不做一个自己的Dynamo, 出去都不好意思跟人打招呼<br />
(<a href="http://twitter.com/xmpp/status/8023241449">http://twitter.com/xmpp/status/8023241449</a>)</p></blockquote>
<p>另外一方面对于Dynamo设计思想也有不少反对的声音，比如2009/11/1在<a href="http://news.ycombinator.com/">Hacker News</a>上链接的一篇文章<a href="http://jsensarma.com/blog/2009/11/dynamo-a-flawed-architecture-part-i/">Dynamo: A flawed architecture</a>引起不少争议，最后竟引起Amazon CTO Werner Vogels在Twitter上回应</p>
<blockquote><p>Darn, someone figured out that Dynamo is a flawed architecture. Luckily its only use is storing hundreds of millions of shopping carts <img src='http://timyang.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
(<a href="http://twitter.com/Werner/statuses/5345892061">http://twitter.com/Werner/statuses/5345892061</a>)<br />
汗，有人发现Dynamo是一个缺陷的架构，幸运的是，我们只用它来存储了成百上亿的购物篮数据。:-)</p></blockquote>
<p>以下是这篇批判Dynamo文章大部分中心观点，所翻译的观点并不代表Tim立场。</p>
<p><strong>&#8211;译文开始&#8211;</strong></p>
<h2>Dynamo: A flawed architecture </h2>
<p>在发表此文章之前，我也争论过Dynamo是否适合我们的系统。但是我很清楚这篇论文充满缺陷，它将错误的引导了读者让大家相信其设计，它的很多设计前后自相矛盾。下文会详细介绍这些缺陷。</p>
<h3>Dynamo的最终一致性</h3>
<p>首先，最终一致性对开发者意味什么呢？</p>
<ol>
<li>写入的数据不能在后续的读操作中获取到。</li>
<li>写入的数据也有可能在后续的读操作中获取到，但读到后可能下一次又读不到。</li>
<li>因此对写操作后面的读取没有SLA(Service Level Agreement)保证。</li>
</ol>
<p>举例说明，由于Dynamo是一个key value存储，我们假设value中存储的是一个list, 当list写入数据之后另外一个client却未读取到，这时候它需要写入数据的话只能重新构建一个新的list，添加要存的值并将新list存入，这就会导致老的list数据丢失。</p>
<p>(Update: 论坛上一些人指出，由于Vector Clock机制，数据丢失的场景不可能出现，我同意，不过我再提出几个其他问题。)</p>
<ol>
<li>Cassandra未用vector clock, 而只用client timestamps也达到了同样效果。</li>
<li>Dynamo依赖合并冲突来解决此问题，一些场合下冲突很难解决。比如从list中错误的截取操作。(if deletion from the list is a valid operation &#8211; then how would one reconcile after mistaken truncation?)</li>
<li>另外一个场景，读取到脏数据后可能会影响后续的写入。(a stale read may end up affecting writes to other keys)</li>
</ol>
<p>一般的常识是读取脏数据是需要避免的，但是Dynamo中无任何措施来避免读取脏数据以及避免读取脏数据的客户端再次写入，这个在单IDC环境其实是完全可以避免的。</p>
<h3>Quorum一致性</h3>
<p>(译者注：Quorum是Dynamo的一个核心特性，主要思想是 写最小节点数W + 读最小节点数R &gt; 所有节点数N)<br />
Dynamo开始就提到系统按最终一致性设计，但是在4.5中却提出用Quorum的方法来实现一定程度的一致性，意思是如果R+W&gt;N, 则读操作就具备(强)一致性了。明显是误导。由于节点会出现不可用的情况，尤其在跨IDC情况下，任一节点随时都有可能离开quorum组，当它离开再加入的时候，R个节点返回的数据就是不一致的，因为故障节点的数据只具备“最终一致性”，而在当时返回的只能是脏数据。</p>
<p>这就带来一个明显的问题，为什么要让未同步到最新数据的节点加入组？答案是Dynamo中无任何方法来判断一个节点是否数据同步，也无法判断有哪些数据不同步。因此只能做一个完全数据比较才能判断，Dynamo中用一种叫Merkle Tree的方法来实现，这个当然是一个代价昂贵且不灵活的操作，因为为了不影响Dynamo正常的读写业务，同步需要在后台执行。</p>
<p>实现强一致性也可以用读取所有节点(R=N)的方式来达到，不过有2个问题。</p>
<ol>
<li> 一旦有一个节点未同步，读取就会失败。</li>
<li>读取的代价极高。</li>
</ol>
<p>我并不是第一个发现这些问题的人，比如另一知名的Cassandra产品<a href="https://issues.apache.org/jira/browse/CASSANDRA-225">Cassandra-225</a>中就提到用一个中心commit log的方法来解决此问题。</p>
<h3>WAN considerations 跨IDC的问题</h3>
<p>值得指出的是，如果将Dynamo部署到多个机房，节点的断续情况会很容易发生。当一个节点连接不到，Dynamo的&#8221;hinted handoff&#8221;策略会使用一致性哈希算法将数据放入下一个节点。在多IDC环境下，下一节点通常在另一机房，因此会造成异地数据传输增加。当异地整个IDC都连不上网络分裂情况发生时，数据需要很长时间才能完全恢复。</p>
<h3>Disaster Recovery 灾难恢复</h3>
<p>Dynamo最终一致性及同步的设计对于是节点故障是有价值的，但是却无法估算有多少数据未同步。如果改用常规的commit log方式的话，很容易就能实现故障恢复并且计算未同步的数据量。</p>
<p>未使用<strong>时间一致性</strong>(译者：基于timestamp的合并？)在某些场合下很难合并冲突。</p>
<h3>一致性还是可用性 Consistency versus Availability</h3>
<p>一般认为Dynamo选择了CAP理论中的AP，而BigTable选择了CA。不幸的是，Dynamo并没有搞清什么是A(availability)和P(Partition Tolerance)。读者被误导只能在C和P中做一个取舍，这个当然是错的。我们很容易在单IDC实现一致性及高可用性。大部分商业数据库就是如此，HBase/HDFS也是如此。</p>
<p>很多人误以为即使在单IDC架构中，Dynamo方式比BigTable/GFS架构更合理。但Dynamo的优势其实是在多IDC。</p>
<h3>中心化还是去中心化</h3>
<p>Dynamo中提到</p>
<blockquote><p>In the past, centralized control has resulted in outages and the goal is to avoid it as much as possible. This leads to a simpler, more scalable, and more available system.<br />
过去，中心化设计导致了很多灾难，我们意识到要远离中心化。去中心化后，系统会更简洁，更具有可扩展性及高可用性。</p></blockquote>
<p>中心化确实会形成瓶颈，但是没有证据说明中心化就低可用性。大部分专业的存储系统通过双机热备的方式都具备高可用性。简单的说，只需要所有中心模块(电源，主板，RAID，交换机等)都按双份的方式来设计，只需要额外增加一点硬件成本，这些系统基本可以达到5个9的可用性。</p>
<p>值得讽刺的是Dynamo其实在部分情况下还是一个中心化的体系，如交换机故障发生了网络分片，服务器分成2个独立的小网，这时候Dynamo对客户端是不可用的，尽管客户端可以连接上Dynamo。</p>
<p>更讽刺的是我们看到Dynamo很多一致性问题都是去中心化设计所导致。</p>
<p><strong>&#8211;译文完&#8211;</strong></p>
<p>此文的讨论也非常精彩，对于想深入了解Dynamo的朋友是不可多得的资料。可参看 <a href="http://news.ycombinator.com/item?id=915212">http://news.ycombinator.com/item?id=915212</a></p>
Similar Posts:<ul><li><a href="http://timyang.net/data/multi-idc-design/" rel="bookmark" title="March 25, 2010">多IDC的数据分布设计(二)</a></li>

<li><a href="http://timyang.net/architecture/yahoo-pnuts/" rel="bookmark" title="June 21, 2009">Yahoo!的分布式数据平台PNUTS简介及感悟</a></li>

<li><a href="http://timyang.net/distributed/multi-idc-consensus/" rel="bookmark" title="February 2, 2010">多IDC的数据分布设计(一)</a></li>

<li><a href="http://timyang.net/architecture/consistent-hashing-practice/" rel="bookmark" title="September 6, 2009">某分布式应用实践一致性哈希的一些问题</a></li>

<li><a href="http://timyang.net/distributed/paxos-scenarios/" rel="bookmark" title="September 23, 2009">Paxos在大型系统中常见的应用场景</a></li>
</ul><!-- Similar Posts took 108.288 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/data/dynamo-flawed-architecture-chinese/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Friendfeed的MySQL key/value存储</title>
		<link>http://timyang.net/data/friendfeed-mysql-schema-less/</link>
		<comments>http://timyang.net/data/friendfeed-mysql-schema-less/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 05:59:06 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[data]]></category>
		<category><![CDATA[friendfeed]]></category>
		<category><![CDATA[key value store]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=447</guid>
		<description><![CDATA[这是一篇2009年初的资料How FriendFeed uses MySQL to store schema-less data,相信大部分人已经看过了。如Fenng的中文介绍FriendFeed 使用 MySQL 的经验。本文从不同的角度再补充下。作者几个月前也曾经在广州技术沙龙作过一次Key value store漫谈的演讲，许多参会人员对key value方向存在强烈的使用意愿，但同时也对完全抛弃MySQL存在疑虑，本文介绍的方案也可以给这些人员一些架构参考。
需求
250M entities, entities表共有2.5亿条记录，当然是分库的。
典型解决方案:RDBMS
问题：由于业务需要不定期更改表结构，但是在2.5亿记录的表上增删字段、修改索引需要锁表，最长需要1小时到1天以上。
Key value方案
评估Document类型数据库，如CouchDB
CouchDB问题： Performance？ 广泛使用？ 稳定性？ 抗压性？
MySQL方案
MySQL相比Document store优点：

 不用担心丢数据或数据损坏
 Replication
 非常熟悉它的特性及不足，知道如何解决

结论
综合取舍，使用MySQL来存储key/value(schema-less)数据,value中可以放：
Python dict
JSON object
实际friendfeed存放的是zlib压缩的Python dict数据，当然这种绑定一种语言的做法具有争议性。
表结构及Index设计模式
feed数据基本上都存在entities表中，它的结构为
mysql&#62; desc entities;
+----------+------------+------+-----+-------------------+----------------+
&#124; Field    &#124; Type       &#124; Null &#124; Key &#124; Default           &#124; Extra          &#124;
+----------+------------+------+-----+-------------------+----------------+
&#124; added_id &#124; int(11)    &#124; NO   &#124; PRI &#124; NULL              &#124; auto_increment &#124;
&#124; id       [...]]]></description>
			<content:encoded><![CDATA[<p>这是一篇2009年初的资料<a href="http://bret.appspot.com/entry/how-friendfeed-uses-mysql">How FriendFeed uses MySQL to store schema-less data</a>,相信大部分人已经看过了。如Fenng的中文介绍<a href="http://www.dbanotes.net/arch/friendfeed_mysql.html">FriendFeed 使用 MySQL 的经验</a>。本文从不同的角度再补充下。作者几个月前也曾经在广州技术沙龙作过一次<a href="http://www.slideshare.net/iso1600/key-value-store">Key value store漫谈</a>的演讲，许多参会人员对key value方向存在强烈的使用意愿，但同时也对完全抛弃MySQL存在疑虑，本文介绍的方案也可以给这些人员一些架构参考。</p>
<h3>需求</h3>
<p><strong>250M entities</strong>, entities表共有2.5亿条记录，当然是分库的。</p>
<h3>典型解决方案:RDBMS</h3>
<p>问题：由于业务需要不定期更改表结构，但是在2.5亿记录的表上增删字段、修改索引需要锁表，最长需要1小时到1天以上。</p>
<h3>Key value方案</h3>
<p>评估Document类型数据库，如CouchDB<br />
CouchDB问题： <strong>Performance？ 广泛使用？ 稳定性？ 抗压性？</strong></p>
<h3>MySQL方案</h3>
<p>MySQL相比Document store优点：</p>
<ul>
<li> 不用担心丢数据或数据损坏</li>
<li> Replication</li>
<li> 非常熟悉它的特性及不足，知道如何解决</li>
</ul>
<h3>结论</h3>
<p>综合取舍，使用MySQL来存储key/value(schema-less)数据,value中可以放：<br />
Python dict<br />
JSON object</p>
<p>实际friendfeed存放的是zlib压缩的Python dict数据，当然这种绑定一种语言的做法具有争议性。</p>
<h3>表结构及Index设计模式</h3>
<p>feed数据基本上都存在entities表中，它的结构为</p>
<pre>mysql&gt; desc entities;
+----------+------------+------+-----+-------------------+----------------+
| Field    | Type       | Null | Key | Default           | Extra          |
+----------+------------+------+-----+-------------------+----------------+
| added_id | int(11)    | NO   | PRI | NULL              | auto_increment |
| id       | binary(16) | NO   | UNI |                   |                |
| updated  | timestamp  | YES  | MUL | CURRENT_TIMESTAMP |                |
| body     | mediumblob | YES  |     | NULL              |                |
+----------+------------+------+-----+-------------------+----------------+</pre>
<p>假如里面存的数据如下</p>
<pre>{
"id": "71f0c4d2291844cca2df6f486e96e37c",
"user_id": "f48b0440ca0c4f66991c4d5f6a078eaf",
"feed_id": "f48b0440ca0c4f66991c4d5f6a078eaf",
"title": "We just launched a new backend system for FriendFeed!",
"link": "http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c",
"published": 1235697046,
"updated": 1235697046,
}</pre>
<p>如果要对link字段进行索引，则用另外一个表来存储。</p>
<pre>mysql&gt; desc index_link;
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| link      | varchar(255) | NO   | PRI |         |       |
| entity_id | binary(16)   | NO   | PRI |         |       |
+-----------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)</pre>
<p>优点是</p>
<ul>
<li> 增加索引时候只需要 1. CREATE TABLE，2.更新程序</li>
<li> 删除索引时候只需要 1. 程序停止写索引表(实际就是一个普通表)，2. DROP TABLE 索引表</li>
</ul>
<p>这种索引方式也是一种值得借鉴的设计模式，特别是key value类型的数据需要索引其中的内容时。</p>
Similar Posts:<ul><li><a href="http://timyang.net/architecture/friendfeed-like-aggregator/" rel="bookmark" title="April 3, 2009">Ideas for creating a friendfeed like feed aggregator system</a></li>

<li><a href="http://timyang.net/tech/key-value-store-draft/" rel="bookmark" title="July 27, 2009">分布式key/value store演讲草稿(一)</a></li>

<li><a href="http://timyang.net/tech/gz-salon-slide/" rel="bookmark" title="August 10, 2009">第一期广州技术沙龙演讲稿及视频</a></li>

<li><a href="http://timyang.net/programming/memcache-mutex/" rel="bookmark" title="July 26, 2010">Memcache mutex设计模式</a></li>

<li><a href="http://timyang.net/web/nginx-module/" rel="bookmark" title="March 17, 2009">如何写nginx module</a></li>
</ul><!-- Similar Posts took 48.907 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/data/friendfeed-mysql-schema-less/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Memcached数据被踢(evictions&gt;0)现象分析</title>
		<link>http://timyang.net/data/memcached-lru-evictions/</link>
		<comments>http://timyang.net/data/memcached-lru-evictions/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 14:17:36 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[data]]></category>
		<category><![CDATA[evictions]]></category>
		<category><![CDATA[LRU]]></category>
		<category><![CDATA[memcached]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=418</guid>
		<description><![CDATA[很多同学可能熟知Memcached的LRU淘汰算法，它是在slab内部进行的，如果所有空间都被slabs分配，即使另外一个slab里面有空位，仍然存在踢数据可能。你可以把slab理解为教室，如果你的教室满了，即使别的教室有空位你的教室也只能踢人才能进人。

本文介绍的却是另外一种现象。今天监控发现线上一memcached发生数据被踢现象，用stats命令看evictions&#62;0,因为以前也出现过此问题，后来对这个参数增加了一个监控，所以这次主动就发现了。由于给memcached分配的内存远大于业务存储数据所需内存，因此初步判断是“灵异现象”。
第一步，netstat查看所有连接，排除是否被一些未规划的client使用，经排查后断定无此可能。
第二步，用tcpdump抽样检查set的指令，排除是否有忘记设cache过期时间的client，初步检查所有典型的业务都有expire time。
第三步，Google，未果
第四步，看源代码，了解evictions计数器增加时的具体细节，oh, no&#8230;
in items.c, memcached-1.2.8,
125         for (search = tails[id]; tries &#62; 0 &#38;&#38; search != NULL; tries--, search=search-&#62;prev) {
126             if (search-&#62;refcount == 0) {
127            [...]]]></description>
			<content:encoded><![CDATA[<p>很多同学可能熟知Memcached的LRU淘汰算法，它是在slab内部进行的，如果所有空间都被slabs分配，即使另外一个slab里面有空位，仍然存在踢数据可能。你可以把slab理解为教室，如果你的教室满了，即使别的教室有空位你的教室也只能踢人才能进人。</p>
<p><img class="alignnone size-full wp-image-422" title="mc" src="http://timyang.net/blog/wp-content/uploads/2009/09/mc.png" alt="mc" width="541" height="196" /></p>
<p>本文介绍的却是另外一种现象。今天监控发现线上一memcached发生数据被踢现象，用stats命令看evictions&gt;0,因为以前也出现过此问题，后来对这个参数增加了一个监控，所以这次主动就发现了。由于给memcached分配的内存远大于业务存储数据所需内存，因此初步判断是“灵异现象”。</p>
<p>第一步，netstat查看所有连接，排除是否被一些未规划的client使用，经排查后断定无此可能。</p>
<p>第二步，用tcpdump抽样检查set的指令，排除是否有忘记设cache过期时间的client，初步检查所有典型的业务都有expire time。</p>
<p>第三步，Google，未果</p>
<p>第四步，看源代码，了解evictions计数器增加时的具体细节，oh, no&#8230;</p>
<p>in items.c, memcached-1.2.8,</p>
<pre>125         for (search = tails[id]; tries &gt; 0 &amp;&amp; search != NULL; tries--, search=search-&gt;prev) {
126             if (search-&gt;refcount == 0) {
127                 if (search-&gt;exptime == 0 || search-&gt;exptime &gt; current_time) {
128                     itemstats[id].evicted++;
129                     itemstats[id].evicted_time = current_time - search-&gt;time;
130                     STATS_LOCK();
131                     stats.evictions++;
132                     STATS_UNLOCK();
133                 }
134                 do_item_unlink(search);
135                 break;
136             }
137         }</pre>
<p>从源代码发现踢数据只判断一个条件，if (search-&gt;refcount == 0)，这个refcount是多线程版本计数用，在当前服务器未启用多线程情况下，refcount应该始终为0,因此初步判断memcached是从访问队列尾部直接踢数据。</p>
<p>为了证实想法，设计以下场景：</p>
<ol>
<li>部署一个memcached测试环境，分配比较小的内存，比如8M</li>
<li>设置1条永远不过期的数据到memcached中，然后再get一次，这条数据后续应该存在LRU队尾。</li>
<li>每隔1S向memcached set(并get一次) 1,000条数据，过期时间设为3秒。</li>
<li>一段时间后，stats命令显示evictions=1</li>
</ol>
<p>按我以前的理解，第2步的数据是永远不会被踢的，因为有足够过期的数据空间可以给新来的数据用，LRU淘汰算法应该跳过没过期的数据，但结果证实这种判断是错误的。以上业务的服务器发生被踢的现象是由于保存了大量存活期短的key/value,且key是不重复的。另外又有一业务保存了小量不过期的数据，因此导致不过期的数据惨遭被挤到队列踢出。</p>
<p>本来这个问题就告一段落了，但在写完这篇文章后，顺便又看了新一代memcached 1.4.1的源代码，很惊喜发现以下代码被增加。</p>
<p>items.c, memcached 1.4.1</p>
<pre>107     /* do a quick check if we have any expired items in the tail.. */
108     int tries = 50;
109     item *search;
110
111     for (search = tails[id];
112          tries &gt; 0 &amp;&amp; search != NULL;
113          tries--, search=search-&gt;prev) {
114         if (search-&gt;refcount == 0 &amp;&amp;
115             (search-&gt;exptime != 0 &amp;&amp; search-&gt;exptime &lt; current_time)) {
116             it = search;
117             /* I don't want to actually free the object, just steal
118              * the item to avoid to grab the slab mutex twice <img src='http://timyang.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />
119              */
120             it-&gt;refcount = 1;
121             do_item_unlink(it);
122             /* Initialize the item block: */
123             it-&gt;slabs_clsid = 0;
124             it-&gt;refcount = 0;
125             break;
126         }
127     }</pre>
<p>重复进行上述测试，未发生evictions。</p>
<p>9/8 Update: 注意到L108的tries=50没有？试想把测试第2步设置51条不过期数据到cache中，情况会怎样？因此新版的Memcached也同样存在本文描述问题。</p>
<p>几条总结：</p>
<ul>
<li> 过期的数据如果没被显式调用get，则也要占用空间。</li>
<li>过期的不要和不过期的数据存在一起，否则不过期的可能被踢。</li>
<li>从节约内存的角度考虑，即使数据会过期，也不要轻易使用随机字符串作为key，尽量使用定值如uid，这样占用空间的大小相对固定。</li>
<li>估算空间大小时候请用slab size计算，不要按value长度去计算。</li>
<li>不要把cache当作更快的key value store来用, cache不是storage。</li>
</ul>
Similar Posts:<ul><li><a href="http://timyang.net/programming/memcache-mutex/" rel="bookmark" title="July 26, 2010">Memcache mutex设计模式</a></li>

<li><a href="http://timyang.net/architecture/twitter-cache-architecture/" rel="bookmark" title="October 28, 2009">Twitter架构图(cache篇)</a></li>

<li><a href="http://timyang.net/tech/twitter-operations/" rel="bookmark" title="November 2, 2009">Twitter系统运维经验</a></li>

<li><a href="http://timyang.net/tech/twitter-whale/" rel="bookmark" title="March 8, 2010">Twitter“鲸鱼”故障技术剖析</a></li>

<li><a href="http://timyang.net/data/mcdb-tt-redis/" rel="bookmark" title="August 11, 2009">MemcacheDB, Tokyo Tyrant, Redis performance test</a></li>
</ul><!-- Similar Posts took 108.540 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/data/memcached-lru-evictions/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>MemcacheDB, Tokyo Tyrant, Redis performance test</title>
		<link>http://timyang.net/data/mcdb-tt-redis/</link>
		<comments>http://timyang.net/data/mcdb-tt-redis/#comments</comments>
		<pubDate>Tue, 11 Aug 2009 12:16:58 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[data]]></category>
		<category><![CDATA[English]]></category>
		<category><![CDATA[memcachedb]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[tokyo cabinet]]></category>
		<category><![CDATA[tokyo tyrant]]></category>

		<guid isPermaLink="false">http://timyang.net/?p=361</guid>
		<description><![CDATA[I had tested the following key-value store for set() and get()

MemcacheDB, use memcached client protocol.
Tokyo Tyrant (Tokyo Cabinet), use memcached client protocol
Redis, use JRedis Java client

1. Test environment
1.1 Hardware/OS
2 Linux boxes in a LAN, 1 server and 1 test client
Linux Centos 5.2 64bit
Intel(R) Xeon(R) CPU E5410  @ 2.33GHz (L2 cache: 6M), Quad-Core * 2
8G memory
SCSI [...]]]></description>
			<content:encoded><![CDATA[<p>I had tested the following key-value store for set() and get()</p>
<ul>
<li><a href="http://memcachedb.org/">MemcacheDB</a>, use memcached client protocol.</li>
<li><a href="http://tokyocabinet.sourceforge.net/tyrantdoc/">Tokyo Tyrant</a> (<a href="http://tokyocabinet.sourceforge.net/">Tokyo Cabinet</a>), use memcached client protocol</li>
<li><a href="http://code.google.com/p/redis/">Redis</a>, use <a href="http://code.google.com/p/jredis/">JRedis</a> Java client</li>
</ul>
<h2>1. Test environment</h2>
<h3>1.1 Hardware/OS</h3>
<p>2 Linux boxes in a LAN, 1 server and 1 test client<br />
Linux Centos 5.2 64bit<br />
Intel(R) Xeon(R) CPU E5410  @ 2.33GHz (L2 cache: 6M), Quad-Core * 2<br />
8G memory<br />
SCSI disk (standalone disk, no other access)</p>
<h3>1.2 Software version</h3>
<p>db-4.7.25.tar.gz<br />
libevent-1.4.11-stable.tar.gz<br />
memcached-1.2.8.tar.gz<br />
memcachedb-1.2.1-beta.tar.gz<br />
redis-0.900_2.tar.gz<br />
tokyocabinet-1.4.9.tar.gz<br />
tokyotyrant-1.1.9.tar.gz</p>
<h3>1.3 Configuration</h3>
<p><strong>Memcachedb startup parameter</strong><br />
Test 100 bytes<br />
./memcachedb -H /data5/kvtest/bdb/data -d -p 11212 -m 2048 <strong>-N -L 8192</strong><br />
(Update: As mentioned by <a href="http://stvchu.org/">Steve</a>, the 100-byte-test missed the -N paramter, so I added it and updated the data)<br />
Test 20k bytes<br />
./memcachedb -H /data5/kvtest/mcdb/data -d -p 11212 -b 21000 -N -m 2048</p>
<p><strong>Tokyo Tyrant (Tokyo Cabinet) configuration</strong><br />
Use default Tokyo Tyrant sbin/ttservctl<br />
use .tch database, hashtable database</p>
<p>ulimsiz=&#8221;256m&#8221;<br />
sid=1<br />
dbname=&#8221;$basedir/casket.tch#bnum=50000000&#8243; # default 1M is not enough!<br />
maxcon=&#8221;65536&#8243;<br />
retval=0</p>
<p><strong>Redis configuration</strong><br />
timeout 300<br />
save 900 1<br />
save 300 10<br />
save 60 10000<br />
# no maxmemory settings</p>
<h3>1.4 Test client</h3>
<p>Client in Java, JDK1.6.0, 16 threads<br />
Use Memcached client java_memcached-release_2.0.1.jar<br />
<a href="http://code.google.com/p/jredis/">JRedis</a> client for Redis test, another <a href="http://code.google.com/p/jdbc-redis/">JDBC-Redis</a> has poor performance.</p>
<h2>2. Small data size test result</h2>
<p>Test 1, 1-5,000,000 as key, 100 bytes string value, do set, then get test, all get test has result.<br />
Request per second(mean)<img class="alignnone size-full wp-image-374" title="key-value-performance-1(Update)" src="http://timyang.net/blog/wp-content/uploads/2009/08/key-value-performance-11.png" alt="key-value-performance-1(Update)" width="652" height="401" /></p>
<table style="width: 270pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0" width="359">
<colgroup span="1">
<col style="width: 130pt;" span="1" width="173"></col>
<col style="width: 70pt;" span="2" width="93"></col>
</colgroup>
<tbody>
<tr style="height: 15.75pt;" height="21">
<td class="xl25" style="border: medium none #d4d0c8; width: 130pt; height: 15.75pt; background-color: transparent;" width="173" height="21"><span style="font-size: small; font-family: Times New Roman;"><strong>Store</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 70pt; background-color: transparent;" width="93"><span style="font-size: small; font-family: Times New Roman;"><strong>Write</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 70pt; background-color: transparent;" width="93"><strong><span style="font-size: small; font-family: Times New Roman;">Read</span></strong></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Memcached</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">55,989 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">50,974 </span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Memcachedb</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">25,583 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">35,260 </span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Tokyo Tyrant</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">42,988 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">46,238 </span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Redis</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">85,765 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">71,708 </span></td>
</tr>
</tbody>
</table>
<p><strong>Server Load Average</strong></p>
<table style="width: 249pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0" width="332">
<colgroup span="1">
<col style="width: 77pt;" span="1" width="102"></col>
<col style="width: 86pt;" span="2" width="115"></col>
</colgroup>
<tbody>
<tr style="height: 15.75pt;" height="21">
<td class="xl25" style="border: medium none #d4d0c8; width: 77pt; height: 15.75pt; background-color: transparent;" width="102" height="21"><span style="font-size: small; font-family: Times New Roman;"><strong>Store</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 86pt; background-color: transparent;" width="115"><span style="font-size: small; font-family: Times New Roman;"><strong>Write</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 86pt; background-color: transparent;" width="115"><strong><span style="font-size: small; font-family: Times New Roman;">Read</span></strong></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Memcached</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">1.80, 1.53, 0.87</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">1.17, 1.16, 0.83</span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">MemcacheDB</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">1.44, 0.93, 0.64</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">4.35, 1.94, 1.05</span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Tokyo Tyrant</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">3.70, 1.71, 1.14</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">2.98, 1.81, 1.26</span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Redis</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">1.06, 0.32, 0.18</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;"><span style="font-size: small; font-family: Times New Roman;">1.56, 1.00, 0.54</span></td>
</tr>
</tbody>
</table>
<h2>3. Larger data size test result</h2>
<p>Test 2, 1-500,000 as key, 20k bytes string value, do set, then get test, all get test has result.<br />
Request per second(mean)<br />
<strong>(Aug 13 Update: fixed a bug on get() that read non-exist key)</strong><br />
<img class="alignnone size-full wp-image-385" title="key-value-performance-2(update)" src="http://timyang.net/blog/wp-content/uploads/2009/08/key-value-performance-21.png" alt="key-value-performance-2(update)" width="646" height="378" /></p>
<table style="width: 270pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0" width="359">
<colgroup span="1">
<col style="width: 130pt;" span="1" width="173"></col>
<col style="width: 70pt;" span="2" width="93"></col>
</colgroup>
<tbody>
<tr style="height: 15.75pt;" height="21">
<td class="xl25" style="border: medium none #d4d0c8; width: 130pt; height: 15.75pt; background-color: transparent;" width="173" height="21"><span style="font-size: small; font-family: Times New Roman;"><strong>Store</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 70pt; background-color: transparent;" width="93"><span style="font-size: small; font-family: Times New Roman;"><strong>Write</strong></span></td>
<td class="xl25" style="border: medium none #d4d0c8; width: 70pt; background-color: transparent;" width="93"><strong><span style="font-size: small; font-family: Times New Roman;">Read</span></strong></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Memcachedb</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">357 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">327 </span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Tokyo Tyrant</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">3,501 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">257 </span></td>
</tr>
<tr style="height: 15.75pt;" height="21">
<td class="xl24" style="border: medium none #d4d0c8; height: 15.75pt; background-color: transparent;" height="21"><span style="font-size: small; font-family: Times New Roman;">Redis</span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">1,542 </span></td>
<td class="xl26" style="background-color: transparent; border: #d4d0c8;" align="right"><span style="font-size: small; font-family: Times New Roman;">957 </span></td>
</tr>
</tbody>
</table>
<h2>4. Some notes about the test</h2>
<p>When test Redis server, the memory goes up steadily, consumed all 8G and then use swap(and write speed slow down), after all memory and swap space is used, the client will get exceptions. So use Redis in a productive environment should limit to a small data size. It is another cache solution rather than a persistent storage. <strong>So compare Redis together with MemcacheDB/TC may not fair because Redis actually does not save data to disk during the test</strong>.</p>
<p>Tokyo cabinet and memcachedb are very stable during heavy load, use very little memory in set test and less than physical memory in get test.</p>
<p>MemcacheDB peformance is poor for write large data size(20k).</p>
<p>The call response time was not monitored in this test.</p>
Similar Posts:<ul><li><a href="http://timyang.net/programming/thrift-protocol-buffers-performance-2/" rel="bookmark" title="April 17, 2009">Thrift and Protocol Buffers performance in Java Round 2</a></li>

<li><a href="http://timyang.net/programming/thrift-protocol-buffers-performance-java/" rel="bookmark" title="April 2, 2009">Thrift and Protocol Buffers performance in Java</a></li>

<li><a href="http://timyang.net/programming/c-erlang-java-performance/" rel="bookmark" title="November 11, 2009">C, Erlang, Java and Go Web Server performance test</a></li>

<li><a href="http://timyang.net/architecture/friendfeed-like-aggregator/" rel="bookmark" title="April 3, 2009">Ideas for creating a friendfeed like feed aggregator system</a></li>

<li><a href="http://timyang.net/python/python-thread-socket-server/" rel="bookmark" title="March 8, 2009">Python thread socket server</a></li>
</ul><!-- Similar Posts took 89.909 ms -->]]></content:encoded>
			<wfw:commentRss>http://timyang.net/data/mcdb-tt-redis/feed/</wfw:commentRss>
		<slash:comments>42</slash:comments>
		</item>
	</channel>
</rss>
