<?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>N.S.thoughts &#187; key/value store</title>
	<atom:link href="http://nightsailer.com/tag/keyvalue-store/feed" rel="self" type="application/rss+xml" />
	<link>http://nightsailer.com</link>
	<description>...silent is golden...</description>
	<lastBuildDate>Wed, 01 Sep 2010 17:01:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Redis &#8211; 有点神奇的data structures server</title>
		<link>http://nightsailer.com/2009/07/19/437.html</link>
		<comments>http://nightsailer.com/2009/07/19/437.html#comments</comments>
		<pubDate>Sun, 19 Jul 2009 04:32:27 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[Technotes]]></category>
		<category><![CDATA[key/value store]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[redis]]></category>

		<guid isPermaLink="false">http://night9.cn/?p=437</guid>
		<description><![CDATA[Redis 早期版本曾经测试过。由于缺乏我需要的PHP/Perl binding,后来就放弃了。
但Redis开发神速，目前已经接近1.0-rc1，据作者自言，可以用了。呵呵。
Redis的神奇之处在于对于value的处理，除了String类型，还增加了Set、List。这点是超越Memcached之所在。
Redis支持对list的pop/push,range原子操作，很容易实现类似Queue,Stack等的数据结构.为此，作者说，可以把redis看做data structures server。
安装
Redis使用posix c编写，所以安装直接make就完事。 运行可以直接用内置配置跑，还是非常方便的。如果一个软件是否能够快速安装测试部署，会得到更多人的青睐。尤其是像需要短时间测试体验类似的东西，要是配置麻烦，我直接就放弃了。
协议
Redis没有使用memcached协议，而是使用自己的一套规范。
速度
Redis的速度很快，110000 SETs/second, 81000 GETs/second。和普通版的memcached相当。
命令
除了针对String的set/get外，redis支持针对Set/List的操作,如LPUSH,RPUSH。
这里有完整的命令列表
多Db
这是另一个有意思的东西，Redis支持不同的db空间，通过selectdb来切换到不同的db空间。从而实现数据的隔离。redis允许key在不同的db之间移动，也支持flush某个db。这个特性可以解决原来memcached中不支持tag/namespace的问题。 
Sharding
和Flare不一样,Redis本身没有内置的sharding功能，而是需要通过client api来实现。比如和libmemcached一样通过实现consistent hashing来实现sharding。
Replication
仅支持简单master-slave。 slave支持只读查询，slave也可以通过上级slave来获得同步数据。
缺陷：
1. redis将所有数据放入内存中，而通过后台进程定时将数据dump到磁盘上，从而实现持久存储。这是redis为什么这么快的原因。因此，如果你的存储数据超过可用内存大小，就会导致OS使用swap文件。作者解释，鱼和熊掌不可兼得，既然要快，就多费点内存吧，反正现在内存也很便宜，呵呵。
2.由于只能通过client端实现sharding，而redis并不支持master之间的复制，因此如何实现动态节点添加和删除，只能由client端来实现。从这个方面说，redis还只能作为一个高级的memcached。
＝＝＝＝＝
我准备测试用Redis解决以下场景的问题:
1. 高速消息队列
2. 访客列表类
常见的最近来访啊，这篇文章谁看过啊，谁谁点评过啊，等等
3. SNS中常见的事件，最近发生了什么
4. 最近更新名单
虽然以上这些通过将数据结构unserialize为string后可以用memcached来实现，但既然redis是data structures server,那么会更加高效好用。
同时，这些数据也不是关键数据，即便丢失也无伤大雅，对于需要可靠保存的数据，要么使用flare，更为安全则应使用传统的数据库。
]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.google.com/p/redis/">Redis</a> 早期版本曾经测试过。由于缺乏我需要的PHP/Perl binding,后来就放弃了。<br />
但Redis开发神速，目前已经接近1.0-rc1，据作者自言，可以用了。呵呵。</p>
<p>Redis的神奇之处在于对于value的处理，除了String类型，还增加了Set、List。这点是超越Memcached之所在。<br />
Redis支持对list的pop/push,range原子操作，很容易实现类似Queue,Stack等的数据结构.为此，作者说，可以把redis看做data structures server。</p>
<p>安装</p>
<p>Redis使用posix c编写，所以安装直接make就完事。 运行可以直接用内置配置跑，还是非常方便的。如果一个软件是否能够快速安装测试部署，会得到更多人的青睐。尤其是像需要短时间测试体验类似的东西，要是配置麻烦，我直接就放弃了。</p>
<p>协议</p>
<p>Redis没有使用memcached协议，而是使用自己的一套<a href="http://code.google.com/p/redis/wiki/ProtocolSpecification">规范</a>。</p>
<p>速度</p>
<p>Redis的速度很快，110000 SETs/second, 81000 GETs/second。和普通版的memcached相当。</p>
<p>命令<br />
除了针对String的set/get外，redis支持针对Set/List的操作,如LPUSH,RPUSH。<br />
这里有<a href="http://code.google.com/p/redis/wiki/CommandReference">完整的命令列表</a></p>
<p>多Db<br />
这是另一个有意思的东西，Redis支持不同的db空间，通过selectdb来切换到不同的db空间。从而实现数据的隔离。redis允许key在不同的db之间移动，也支持flush某个db。这个特性可以解决原来memcached中不支持tag/namespace的问题。 </p>
<p>Sharding<br />
和Flare不一样,Redis本身没有内置的sharding功能，而是需要通过client api来实现。比如和libmemcached一样通过实现consistent hashing来实现sharding。</p>
<p>Replication<br />
仅支持简单master-slave。 slave支持只读查询，slave也可以通过上级slave来获得同步数据。</p>
<p>缺陷：<br />
1. redis将所有数据放入内存中，而通过后台进程定时将数据dump到磁盘上，从而实现持久存储。这是redis为什么这么快的原因。因此，如果你的存储数据超过可用内存大小，就会导致OS使用swap文件。作者解释，鱼和熊掌不可兼得，既然要快，就多费点内存吧，反正现在内存也很便宜，呵呵。<br />
2.由于只能通过client端实现sharding，而redis并不支持master之间的复制，因此如何实现动态节点添加和删除，只能由client端来实现。从这个方面说，redis还只能作为一个高级的memcached。</p>
<p>＝＝＝＝＝<br />
我准备测试用Redis解决以下场景的问题:<br />
1. 高速消息队列<br />
2. 访客列表类<br />
常见的最近来访啊，这篇文章谁看过啊，谁谁点评过啊，等等<br />
3. SNS中常见的事件，最近发生了什么<br />
4. 最近更新名单<br />
虽然以上这些通过将数据结构unserialize为string后可以用memcached来实现，但既然redis是data structures server,那么会更加高效好用。<br />
同时，这些数据也不是关键数据，即便丢失也无伤大雅，对于需要可靠保存的数据，要么使用flare，更为安全则应使用传统的数据库。</p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2009/07/19/437.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flare－兼容Memcached协议的分布式(key/value store)键值存储系统</title>
		<link>http://nightsailer.com/2009/07/19/421.html</link>
		<comments>http://nightsailer.com/2009/07/19/421.html#comments</comments>
		<pubDate>Sat, 18 Jul 2009 16:40:21 +0000</pubDate>
		<dc:creator>nightsailer</dc:creator>
				<category><![CDATA[Technotes]]></category>
		<category><![CDATA[distributed storage]]></category>
		<category><![CDATA[flare]]></category>
		<category><![CDATA[key/value store]]></category>
		<category><![CDATA[memcached]]></category>

		<guid isPermaLink="false">http://night9.cn/?p=421</guid>
		<description><![CDATA[Flare, Green Lab开发的开源产品,底层使用TC, 完全兼容Memcached协议（ASCII，非binary)。主要有以下特性:

支持Master/slave复制
支持master 分区
支持动态节点添加删除，可以failover
持久存储

现在似乎大家都很关心好的key/value存储方案。作为传统数据库的补充。Memcached由于缺乏持久存储功能，因此无法作为一个可靠的key/value方案。
我之前关注过基于Memcached派生的一些方案，包括
memcachedb &#8211; 新浪团队的,bdb+memcached协议
tokyo tyrant  &#8211; TC+memcached网络接口
LightCloud 在Tokyo Tyrant上实现了多节点的分布式管理。
repcached － 在memcached源码基础上增加复制功能
redist - 除了string，还允许存储list、set等类型
除了上述软件，还有一些用Erlang,Java的方案,我并没有考虑。首先，我的使用场景还没有大到那个地步，我希望选择一个性价比更高的中低端方案  
这其中，最关注的是TT(Toyko tyrant)。 但TT令我不太满意的是对于memcached的协议的兼容性并不够好，比如不能正确处理过期，也不能处理flag。导致客户端无法正常解压缩和unserialize,虽然在client端都能处理，不过当时是打算作为一个session storage,无法自动过期就比较麻烦，解决方案是通过在TT端执行lua可以进行gc处理，总体感觉不够完满。
memcachedb 对于存储定长字段不错，但不固定长度记录的存储似乎不够好，也没有现行的例子。
repcached 仅仅是支持mm复制，但无法正面解决持久存储的问题。
redist 当初测试时缺乏我需要的api。不过目前已经有了PHP PECL版本的api。 redist的复制机制现在也有了很大的改进。redist的应用实例不多。但是，我认为它和mongoDb一样，值得持续关注。
flare 则是最后选择的。经过测试，虽然速度上没有其他那么快，但其良好的扩展能力让我非常满意。此外，对于memcached协议的兼容性也做的很好。
还有1个特性，flare的key可以超过256bytes,而value可以超过1mb。 传统memcached由于内存分配策略因此有上述限制。
flare的底层存储是可以扩展的，目前使用的是tc(tokyo cabinet)。
从这个结构上看，倒是一个tt的很好替代品。
flare的运行性能还是不错，目前在GREE中得到实际应用，摘自项目网站描述：
Flare is running at GREE (one of the major SNS services in Japan) w/ 6 masters and 6 slaves (over 2,000M keys), and 500-1,000 qps (load [...]]]></description>
			<content:encoded><![CDATA[<p>Flare, Green Lab开发的开源产品,底层使用TC, 完全兼容Memcached协议（ASCII，非binary)。主要有以下特性:</p>
<ul>
<li>支持Master/slave复制</li>
<li>支持master 分区</li>
<li>支持动态节点添加删除，可以failover</li>
<li>持久存储</li>
</ul>
<p>现在似乎大家都很关心好的key/value存储方案。作为传统数据库的补充。Memcached由于缺乏持久存储功能，因此无法作为一个可靠的key/value方案。<br />
我之前关注过基于Memcached派生的一些方案，包括<br />
<a href="http://memcachedb.org/">memcachedb</a> &#8211; 新浪团队的,bdb+memcached协议<br />
<a href="http://tokyocabinet.sourceforge.net/tyrantdoc/">tokyo tyran</a>t  &#8211; TC+memcached网络接口<br />
<a href="http://opensource.plurk.com/LightCloud/">LightCloud</a> 在Tokyo Tyrant上实现了多节点的分布式管理。</p>
<p><a href="http://repcached.lab.klab.org/">repcached</a> － 在memcached源码基础上增加复制功能<br />
<a href="http://code.google.com/p/redis/">redist </a>- 除了string，还允许存储list、set等类型</p>
<p>除了上述软件，还有一些用Erlang,Java的方案,我并没有考虑。首先，我的使用场景还没有大到那个地步，我希望选择一个性价比更高的中低端方案 <img src='http://nightsailer.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>这其中，最关注的是TT(Toyko tyrant)。 但TT令我不太满意的是对于memcached的协议的兼容性并不够好，比如不能正确处理过期，也不能处理flag。导致客户端无法正常解压缩和unserialize,虽然在client端都能处理，不过当时是打算作为一个session storage,无法自动过期就比较麻烦，解决方案是通过在TT端执行lua可以进行gc处理，总体感觉不够完满。<br />
memcachedb 对于存储定长字段不错，但不固定长度记录的存储似乎不够好，也没有现行的例子。<br />
repcached 仅仅是支持mm复制，但无法正面解决持久存储的问题。</p>
<p>redist 当初测试时缺乏我需要的api。不过目前已经有了PHP PECL版本的api。 redist的复制机制现在也有了很大的改进。redist的应用实例不多。但是，我认为它和mongoDb一样，值得持续关注。</p>
<p>flare 则是最后选择的。经过测试，虽然速度上没有其他那么快，但其良好的扩展能力让我非常满意。此外，对于memcached协议的兼容性也做的很好。<br />
还有1个特性，flare的key可以超过256bytes,而value可以超过1mb。 传统memcached由于内存分配策略因此有上述限制。<br />
flare的底层存储是可以扩展的，目前使用的是tc(tokyo cabinet)。<br />
从这个结构上看，倒是一个tt的很好替代品。</p>
<p>flare的运行性能还是不错，目前在GREE中得到实际应用，摘自项目网站描述：</p>
<p>Flare is running at GREE (one of the major SNS services in Japan) w/ 6 masters and 6 slaves (over 2,000M keys), and 500-1,000 qps (load average is nearly 0.00&#8230;).</p>
<p>看起来很诱人。因为同样TT超过100M的key，性能会直线下降。plurk的lightclound通过多节点的负载均衡解决了这个问题。（btw,plurk.com目前是被和谐中,要想取得lightclound源码还需要穿墙，唉)</p>
<p>以下是在我的osx上进行的安装测试。</p>
<p>1. 首先下载源码</p>
<p>http://labs.gree.jp/Top/OpenSource/Flare/Download-en.html</p>
<p>2. 使用port安装boost</p>
<p>$ port<br />
install boost</p>
<p>3. 安装tc</p>
<p>http://tokyocabinet.sourceforge.net/</p>
<p>4. 编译flare<br />
tar zxvf flare-1.0.8.tgz<br />
./configure &#8211;with-boost=/opt/local &#8211;prefix=/opt/flare<br />
make install</p>
<p>flare编译后只有2个文件<br />
flarei,flared<br />
分别是index server和node server.<br />
很清爽啊。</p>
<p>5.运行<br />
flare sources下有一个etc目录，中间分别有index server, node server的配置。<br />
可以直接复制到/opt/flare/etc<br />
然后使用<br />
flared &#8211;daemonize -f <config_path><br />
flarei &#8211;daemonize -f <config_path></p>
<p>就可以跑起来了。</p>
<p>6.概念<br />
Flare有几个概念，需要理解<br />
index server<br />
这是索引服务器，用于控制node server的状态<br />
注意，client并不直接和index server进行交互。<br />
node server<br />
这是实际存储节点. node有3种role:<br />
master/slave/proxy<br />
master是主节点,slave是分流节点，用于同步复制master<br />
proxy则将client的请求转发到当前合适的节点(包括master/slave)。<br />
有的人不太理解为什么要用proxy，是否多此一举，而实际测试表明，<br />
通过proxy转发的请求的确要比直接connect到实际节点速度差很多。<br />
这是因为，flare是一个集群，其中的node server是可以动态添加，删除的。<br />
当某个node down后，index server会检测到，并标志其state为down。<br />
此外，master 支持partition，因此通过proxy节点，client无需处理这些复杂问题。<br />
根据作者的建议, proxy node应该和client本地运行，这样可以减少多余的tcp请求。</p>
<p>下面是我写的一个脚本，用于搭建一个典型的测试场景：<br />
1个index server<br />
2个master node,启用partition<br />
1个slave，启用balance</p>
<p>由于flare把ip:port作为一个node，因此只需要1个ip，不同的port就可以快速实现测试需要的环境。</p>
<p>$./start_flare.sh<br />
#启动index server,监听 127.0.0.1:12120<br />
flarei &#8211;daemonize -f /opt/flare/etc/flarei.conf<br />
#proxy<br />
flared &#8211;daemonize &#8211;data-dir /opt/flare/var/data/d0 &#8211;index-server-name 127.0.0.1 &#8211;index-server-port 12120 &#8211;server-name 127.0.0.1 &#8211;server-port 12121<br />
#master1 node<br />
flared &#8211;daemonize &#8211;data-dir /opt/flare/var/data/d1 &#8211;index-server-name 127.0.0.1 &#8211;index-server-port 12120 &#8211;server-name 127.0.0.1 &#8211;server-port 12122<br />
#slave node<br />
#flared &#8211;daemonize &#8211;data-dir /opt/flare/var/data/d2 &#8211;index-server-name 127.0.0.1 &#8211;index-server-port 12120 &#8211;server-name 127.0.0.1 &#8211;server-port 12123<br />
#master2<br />
#flared &#8211;daemonize &#8211;data-dir /opt/flare/var/data/d3 &#8211;index-server-name 127.0.0.1 &#8211;index-server-port 12120 &#8211;server-name 127.0.0.1 &#8211;server-port 12124<br />
echo &#8220;waiting dameon startup&#8230;&#8221;<br />
sleep 3<br />
echo &#8220;set nodes role&#8230;.&#8221;</p>
<p># 当某个node加入时,默认是proxy role，因此需要修改这些role<br />
# 通过telnet到index server，可以执行这些命令,我们在脚本中可以使用<br />
# nc来自动执行</p>
<p># node role的命令格式：<br />
# node role server port master|slave|proxy  balance partiion</p>
<p>echo &#8220;node role 127.0.0.1 12122 master 1 0&#8243;|nc 127.0.0.1 12120<br />
# 设置为slave, balance 为2,给于2倍read权重<br />
echo &#8220;node role 127.0.0.1 12123 slave 2 0&#8243;|nc 127.0.0.1 12120<br />
# 第2个master node,将partition设置为1，表明这是第2个partion，允许<br />
＃将部分数据从原来的master 同步过来<br />
echo &#8220;node role 127.0.0.1 12124 master 1 1&#8243;|nc 127.0.0.1 12120<br />
sleep 2<br />
echo &#8220;stats nodes&#8221;|nc 127.0.0.1 12120</p>
<p>STAT 127.0.0.1:12121:role proxy<br />
STAT 127.0.0.1:12121:state down<br />
STAT 127.0.0.1:12121:partition -1<br />
STAT 127.0.0.1:12121:balance 0<br />
STAT 127.0.0.1:12121:thread_type 16<br />
STAT 127.0.0.1:12122:role master<br />
STAT 127.0.0.1:12122:state down<br />
STAT 127.0.0.1:12122:partition 0<br />
STAT 127.0.0.1:12122:balance 1<br />
STAT 127.0.0.1:12122:thread_type 17<br />
STAT 127.0.0.1:12123:role slave<br />
STAT 127.0.0.1:12123:state prepare<br />
STAT 127.0.0.1:12123:partition 0<br />
STAT 127.0.0.1:12123:balance 0<br />
STAT 127.0.0.1:12123:thread_type 18<br />
STAT 127.0.0.1:12124:role master<br />
STAT 127.0.0.1:12124:state prepare<br />
STAT 127.0.0.1:12124:partition 1<br />
STAT 127.0.0.1:12124:balance 1<br />
STAT 127.0.0.1:12124:thread_type 19<br />
END</p>
<p>stats nodes可以列出当前各个节点的状态信息<br />
注意, 有些节点的state是prepare，表明正在进行同步复制。</p>
<p>我进行了一个简单的测试, 分别读写1M 记录，<br />
测试代码</p>
<pre>
<code>
?php
$host = $argv[1];
$port = $argv[2];
set_time_limit(0);
echo "connect to $host $port \n";
$memcached = new Memcached();
$memcached->addServer($host,$port);

$loop = 1000000;
echo "start set tests...\n";
$start =microtime(true);
for ($i=0; $i < $loop; $i++) {
    $memcached->set(md5("k$i"),md5("k$i"));
}
$end = microtime(true);
echo "ok.\n";
$total1 = $end-$start;
echo "start get tests...\n";
$start =microtime(true);
for ($i=0; $i < $loop; $i++) {
    $memcached->get(md5("k$i"));
}
$end = microtime(true);
$total2 = $end-$start;
echo "ok.\n";
echo "set time:$total1 ",$loop/$total1,' rps',"\n";
echo "get time:$total2 ",$loop/$total2, ' rps',"\n";
?>
</code>
</pre>
<p>当单节点执行set/get操作时，速度和memcached<br />
的ascii模式基本一样，rps只略低几百个。<br />
但是使用proxy 节点后，只有原来的一半。</p>
<p>============<br />
推荐的Flare的适用场景:<br />
1. 最正统的就是key/value storage。我自己将flare作为doggy中dhash的后端实现。<br />
2. Session Storage。 比如PHP，可以直接适用memcached的session_handler。由于是持久的，因此解决原来memcached的尴尬和困扰。<br />
3. 其他的基于key/value的扩展方案</p>
<p>Flare可以直接替代Memcached么？<br />
答案是否。Flare的优势和本质是分布式key/value的持久存储，而不是作为一个cache。作为一个caching方案，要比memcached差很多。<br />
尤其是启用了binary protocol后，memcached的优势很明显。</p>
]]></content:encoded>
			<wfw:commentRss>http://nightsailer.com/2009/07/19/421.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
