原址如下:
http://blog.nosqlfan.com/html/3066.html
http://www.54chen.com/_linux_/riak-source.html
Riak源码阅读手记系列文章
Riak是一个类Dynamo模型的key-value存储,用Erlang实现,并由Basho公司开源并主要开发维护。本文推荐的系列文章来自五四陈科学院,作者是@54chen(陈臻)。系列文章已经发表五篇,内容短小精悍而又内容丰富,推荐给大家,NoSQLFan会保持后续更新。
- riak源码阅读手记一 初出茅庐 项目入口
- riak源码阅读手记二 左右开弓 启动
- riak源码阅读手记三 运行安装
- riak源码阅读手记四 与Cassandra相比
- riak源码阅读手记五 压力测试
- riak源码阅读手记 操作列表及supervisorTree一览
riak源码阅读手记一 初出茅庐 项目入口
Posted on
2011-08-22
by
54chen
简介
basho(相扑)是一家美国的技术公司,专营数据存储和管理软件,11年6月30日获得了750万美元的融资。basho将riak开源,通过收取riak的维护和管理界面软件的使用费用来赚钱,和resin的公司类似。
今天主要研究的是,basho旗下的riak:一个类dynamo系统的kv存储。riak使用了erlang进行开发,将代码精简到极致。
rebar
riak的代码使用了一个叫做rebar(钢筋)的erlang构建工具,使用起来真的很方便,其使用方法建议参考这篇文章:http://www.linezing.com/blog/?p=347。每个项目下,都有一个叫做rebar.config的文件,里面用erlang语法记录了这个项目需要的目录、环境、版本、以及依赖的包在github上的位置。真的很方便。riak项目中,rebar和reltool被大量使用。reltool使用方法参见 http://erlangdisplay.iteye.com/blog/508944
riak的总控工程:https://github.com/basho/riak。
看rebar.config定义的依赖部分:
{deps, [
{cluster_info, "1.1.*", {git, "git://github.com/basho/cluster_info", {branch, "master"}}}, %% 这个模块提供了一个松散易扩展的导出集群节点状态的办法。可以收集的信息包括:时间、所有的erlang进程的静态统计、网络连接情况、cpu和内存、大队列进程、内部内存调用统计、ETS、各节点的名字版本等
{luwak, "1.*", {git, "git://github.com/basho/luwak", {branch, "master"}}}, %% 大对象存储。用来存音频视频啥的。
{riak_kv, "0.14.*", {git, "git://github.com/basho/riak_kv", {branch, "master"}}}, %% 这个模块依赖riak_core,在这一层里,封装了给各种client调用的接口,处理具体存储、M/R等。
{riak_search, "0.14.*", {git, "git://github.com/basho/riak_search",
{branch, "master"}}} %% 基于riak的全文检索实现
]}.
构建过程
通过rebar的reltool支持,在riak项目中,rebar.conf中定义了{sub_dirs,["rel"]},表示在rel目录下使用reltool创建一个发行版本。
在rel目录的rel.config中,{lib_dirs, ["../deps"]},定义了所有的子模块都放在了deps目录下。很长的一个config文件,有点像ant脚本。
函数规范定义:spec
-spec Module:Function(ArgType1, ..., ArgTypeN) -> ReturnType.
函数的参数数目必须与函数规范定义相同,否则编译出错。定义了type及spec,我们可以使用 dialyzer 对代码进行静态分析,在运行之前发现很多低级或者隐藏的错误。
riak源码阅读手记二 左右开弓 启动
riak源码阅读手记二 左右开弓 启动
Posted on
2011-08-24
by
54chen
目标系统(target system)
OTP系统定义里有这么一个东西:
可以被一般的erl脚本启动的系统叫基础目标系统;
除此之外还可以做运行时代码替换的系统叫简单目标系统;
如果还支持日志输出到文件、自动定时启动的话就叫做内嵌目标系统。
启动目标系统的方式
通过erlang/OTP标准的reltool工具生成的目标系统,可以用多种方式灵活启动。
第一种:
os> /usr/local/erl-target/bin/erl
这只启动了一个基础目标系统。基本没什么具体功能。
第二种:
os> /usr/local/erl-target/bin/erl -boot /usr/local/erl-target/releases/FIRST/start
用-boot参数,这可以启动一个简单目标系统。releases/RELEASES文件可用来做热替换。
第三种:
bin/start
这个脚本会去调用 bin/run_erl ,最终调用 bin/start_erl启动。run_erl是一个提供运行时日志输出到文件的封装。还提供了简单的机制attach到一个erlang shell。
自定义behaviour
-spec behaviour_info(atom()) -> 'undefined' | [{atom(), arity()}].
behaviour_info(callbacks) ->
[{start,2}, % (Partition, Config)
{stop,1}, % (State)
{get,2}, % (State, BKey)
{put,3}, % (State, BKey, Val)
{list,1}, % (State)
{list_bucket,2}, % (State, Bucket)
{delete,2}, % (State, BKey)
{drop,1}, % (State)
{fold,3}, % (State, Folder, Acc), Folder({B,K},V,Acc)
{is_empty,1}, % (State)
{callback,3}]; % (State, Ref, Msg) ->
behaviour_info(_Other) ->
undefined.
上述就是一个自定义的behaviour,使用的时候:
-behaviour(xxx).
...
有点类似java的interface.
riak源码阅读手记 运行安装
代码运行入口
riak-kv/ebin/riak_kv.app文件定义了otp标准项目的结构,一个不错的实例:http://www.iteye.com/topic/342819
{mod, {riak_kv_app, []}}一行定义了入口。打开riak_kv_app文件:
-export([start/2,stop/1]).
定义了两大个方法,start和stop。
先看start:
启动riak_kv及相关的server。
检查系统时间。
加入系统变量。
确保设置NWR的值和一些vclock的初始值。
看storage_backend是否启动。
在cluster_info中注册。
启动supervisor。
全部启动。
stop:application:stop。
跑一把试试:
A机:192.168.103.10
B机:192.168.97.48
C机:192.168.100.52
三个节点,已经装好erlang R13B04。
先在A机操作:
wget http://downloads.basho.com/riak/riak-0.14/riak-0.14.2.tar.gz
tar zxvf riak-0.14.2.tar.gz
cd riak-0.14.2
make rel
然后在rel/riak目录下会有最编译好的节点程序。
scp -r rel [email protected]:/root/
scp -r rel [email protected]:/root/
cd rel/riak
ABC三机修改配置:
vim etc/app.config
把127.0.0.1修改为对应的ip
vim etc/vm.args
同上。
A:bin/riak start
B: bin/riak start
bin/riak-admin join [email protected]
C: bin/riak start
bin/riak-admin join [email protected]
./riak-admin status
欧了。
此时默认使用bitcask做为存储引擎。
riak源码阅读手记 与Cassandra相比
实现上:
1)虽然二者都是dynamo的实现,具体方法还是不一样的,riak更忠于dynamo的原文档,实现了所有文档提到的关键点。同时还增加了map reduce和links等功能。
2)Cassandra略去了一些文档里的关键点:向量时钟、按照key范围的大分区等。增加了一些方法如:范围查询、固定分区。
扩展:
1) riak提供了bin/riak join这样的命令来加入新的节点,基本完全按照dynamo文档所说的一样来实现了,从多个节点去获取原来的负载和数据回来,每个节点的压力都可以得到平衡。
2)相比之下,Cassandra集群的节点需要计算数据的一个范围。当加入节点时,Cassandra的策略是分出来相应分区上一半的范围去新节点。这点在一个Cassandra集群需要加节点时会很痛苦,可能会存在两个节点之间大规模的数据转移。
查询和分布:
1)riak有map reduce。
2)Cassandra可以接hadoop达到M/R的效果。
写冲突检查:
1)riak使用了向量时钟。
2)Cassandra使用了timestamp。如果时间有问题,可能会丢。
数据模型:
1)riak有bucket的概念,每个buckect可动态建立,每个buckect的数据模型都不一样。
2)Cassandra的keyspace与列簇都是依赖xml定义的,如果要修改,需要重启。
API:
1)riak提供了http与protocol buffers两种
2)Cassandra使用thrift
可配置的存储:
1)riak默认是bitcast存储,还有innodb,开发者很勤快,甚至还有leveldb。
2)Cassandra一直就是SSTable。
riak源码阅读手记 压力测试
基础环境:
三个台式机
一次操作:
操作一段购物车数据,先写包括3个货物的数据,然后取出来,再加上三个后存入。
压力结果:
1) 10个线程,无连接池化,每次新连接。PBClient。每次req包括上述一次操作里的一写一读一写三次。
Rate: 122 req/s
Rate: 103 req/s
Rate: 119 req/s
Rate: 110 req/s
Rate: 117 req/s
Rate: 116 req/s
Rate: 121 req/s
Rate: 110 req/s
Rate: 116 req/s
Rate: 111 req/s
Rate: 123 req/s
Rate: 122 req/s
Rate: 119 req/s
Rate: 123 req/s
Rate: 110 req/s
三个节点平均load为小于1。
2)50个线程,无连接池化,每次新连接。PBClient。每次req包括上述一次操作里的一写一读一写三次。
Rate: 124 req/s
Rate: 119 req/s
Rate: 124 req/s
Rate: 127 req/s
Rate: 114 req/s
Rate: 103 req/s
Rate: 93 req/s
Rate: 110 req/s
Rate: 120 req/s
Rate: 117 req/s
Rate: 121 req/s
Rate: 119 req/s
Rate: 109 req/s
三个节点平均load为1。接入节点load略高。
3)100个线程,无连接池化,每次新连接。PBClient。每次req包括上述一次操作里的一写一读一写三次。
Rate: 89 req/s
Rate: 109 req/s
Rate: 97 req/s
Rate: 108 req/s
Rate: 105 req/s
Rate: 105 req/s
Rate: 105 req/s
Rate: 106 req/s
Rate: 104 req/s
Rate: 106 req/s
Rate: 103 req/s
Rate: 91 req/s
三个节点平均load为1。接入节点load为大于2。
以上数据为从一个节点打入数据,接入节点负载略高。无池化,在建立连接浪费可能比较多。进行改进,合并发起连接的过程和接入节变成所有节点。
1)三个节点共同接入,最大连接数150,相当于池化连接,150个线程,PBClient。
Rate: 271 req/s
Rate: 275 req/s
Rate: 256 req/s
Rate: 276 req/s
Rate: 287 req/s
Rate: 288 req/s
Rate: 280 req/s
Rate: 293 req/s
Rate: 279 req/s
Rate: 291 req/s
Rate: 254 req/s
Rate: 287 req/s
Rate: 288 req/s
Rate: 283 req/s
Rate: 292 req/s
平均load 1,无明显负载偏移。
2)三个节点共同接入,最大连接数300,相当于池化连接,300个线程,PBClient。
Rate: 273 req/s
Rate: 234 req/s
Rate: 264 req/s
Rate: 264 req/s
Rate: 263 req/s
Rate: 277 req/s
Rate: 253 req/s
Rate: 250 req/s
Rate: 258 req/s
Rate: 218 req/s
Rate: 237 req/s
Rate: 268 req/s
Rate: 232 req/s
Rate: 245 req/s
Rate: 247 req/s
平均load 1.5,无明显负载偏移。
同机器的mysql性能压测结论为:http://www.54chen.com/java-ee/amoeba-benchmark-report.html
可得到比mysql qps高3倍以上(因为riak的压测中每req为2写1读)。
riak源码阅读手记 操作列表及supervisorTree一览
Posted on
2011-10-18
by
54chen
基于0.14.2的记录,1.0的变化会在后续记录。
riak源码阅读手记一 初出茅庐 项目入口
http://www.54chen.com/_linux_/riak-source.html
riak源码阅读手记二 左右开弓 启动
http://www.54chen.com/_linux_/riak-cource-code.html
riak源码阅读手记 运行安装
http://www.54chen.com/_linux_/riak-source-install-run.html
一些常用的指令:
http://wiki.basho.com/Command-Line-Tools.html#riak-admin
riak源码阅读手记 压力测试
http://www.54chen.com/_linux_/riak-benchmark.html
riak源码阅读手记 操作列表及supervisorTree一览
http://www.54chen.com/_linux_/riak-source-notes-operation-supvisor-detail.html
[山寨收集操作列表]
看系统状况,有各种内存cpu硬盘的情况
bin/riak-admin status
节点更换新的ip地址:
如果是所有的节点都换,那在停下来集群,在每个节点都依次运行:
./riak-admin reip [email protected] [email protected]
./riak-admin reip [email protected] [email protected]
./riak-admin reip [email protected] [email protected]
依次去对应的节点,修改etc:
- sed -i 's/192.168.103.9/10.235.2.226/g' app.config
- sed -i 's/192.168.103.9/10.235.2.226/g' vm.args
-
- sed -i 's/192.168.97.48/10.235.2.183/g' app.config
- sed -i 's/192.168.97.48/10.235.2.183/g' vm.args
-
- sed -i 's/192.168.100.52/10.235.2.138/g' app.config
- sed -i 's/192.168.100.52/10.235.2.138/g' vm.args
进入运行着的集群:
./riak attach
ctrl+d退出
看ring的分布情况:
>{ok,Ring} = riak_core_ring_manager:get_my_ring().
[看一点代码]
riak_kv_app -> riak_core->riak_core_sup[supervisor]->
riak_core_sup
|-riak_core_handoff_manager handoff管理 gen_server
|-riak_core_handoff_listener handoff接收 gen_nb_server
|-riak_core_ring_events 处理ring变化 gen_event
|-riak_core_ring_manager ring管理 gen_server2
|-riak_core_node_watcher_events 节点侦察 gen_event
|-riak_core_node_watcher 节点 gen_server
|-riak_core_gossip gossip协议 gen_server
[riak里的自定义behaviour]
-gen_nb_server from gen_server
-gen_server2 gen_server的一个拷贝 增加了pxxx的办法及增加了许多参数
-riak_core_vnode from gen_fsm
riak_kv:
-riak_kv_backend Riak backend behaviour