Riak Core 2,riakcore
Riak Core 2,riakcore
Learn Riak Core Step By Step 2
Riak Core, The Coordinator
What is a Coordinator?
顾名思义, Coordinator
即使一个协调者,主要工作就是用来协调进来的请求。它强行执行N,
R, and W
的一致性语义,并且执行想read repair
的anti-entropy
服务。足药用在分布式集群中,当出现冲突时,用来同步数据。
从技术上说, 协调器是一个gen_fsm
,每一个请求都会被他自己的erlang进程处理,一个协调器会和vnode保持通信,直请求结束。
一个协调器总的来说:
- 协调请求
- 强一致性
- 执行
anti-entropy
- 一个实现了
gen-fsm
行为的erlang进程 - 与执行请求的vnode实例保持通信
Implementing a Coordinator
和vnode不一样,riak core没有定义协调器的行为。例子中现实了get和put的协调器,可以参照,但不是一成不变的。
例子中使用supervisour和gen_fsm worker的方式实现了协调器。
init(Args) -> {ok, InitialState, SD, Timeout}
Args :: term() InitialState :: atom() SD :: term() Timeout :: integer()
这实际上是gen_fsm行为的一部分,必须在回调中制定初始状态名和数据(SD)。有些情况下,你也可以制定超时的值为0以至于马上进入到初始状态-prepare
。
一个get rts的协调器需要4个参数:
-
RequestId:本次请求的唯一Id
-
From: 应答者
-
Client: The name of the client entity -- the entity that is writing log events to RTS.
-
StatName: 统计项的名字.
init([ReqId, From, Client, StatName]) -> SD = #state{req_id=ReqId, from=From, client=Client, stat_name=StatName}, {ok, prepare, SD, 0}.
rts的写协调者也是一样,但是有两个额外的参数。
-
Op: 执行的操作可以是
set
,append
,incr
,incrby
或者sadd
中的一种. -
Val: 被操作的值,
incr
操作没有这项定义。
init([ReqID, From, Client, StatName, Op, Val]) -> SD = #state{req_id=ReqID, from=From, client=Client, stat_name=StatName, op=Op, val=Val}, {ok, prepare, SD, 0}.
prepare(timeout, SD0) -> {next_state, NextState, SD, Timeout}
SD0 = SD :: term() NextState :: atom() Timeout :: integer()
prepare
的工作是建立一个优先列表,这个列表是应该参与本次请求的优先的vnode集合的列表.大部分的工作都被riak_core_util:chash_key/1
和riak_core_apl:get_apl/3
做完了.get
和write
协调器这时后做的工作都一样。
计算请求落在环的索引,从索引中确定N个优先处理这个请求的分区。
下面是代码:
prepare(timeout, SD0=#state{client=Client, stat_name=StatName}) -> DocIdx = riak_core_util:chash_key({list_to_binary(Client), list_to_binary(StatName)}), Prelist = riak_core_apl:get_apl(DocIdx, ?N, rts_stat), SD = SD0#state{preflist=Prelist}, {next_state, execute, SD, 0}.
execute(timeout, SD0) -> {next_state, NextState, SD}
SD0 = SD :: term() NextState :: atom()
prepare之后就会调用excute,excute会根据优先列表来执行相应的stat
请求。
execute(timeout, SD0=#state{req_id=ReqId, stat_name=StatName, preflist=Prelist}) -> rts_stat_vnode:get(Prelist, ReqId, StatName), {next_state, waiting, SD0}.
写协调器和get
协调器一样,就是多了op
.
execute(timeout, SD0=#state{req_id=ReqID, stat_name=StatName, op=Op, val=undefined, preflist=Preflist}) -> rts_stat_vnode:Op(Preflist, ReqID, StatName), {next_state, waiting, SD0}.
waiting(Reply, SD0) -> Result
Reply :: {ok, ReqID} Result :: {next_state, NextState, SD} | {stop, normal, SD} NextState :: atom() SD0 = SD :: term()
下面是get的代码
waiting({ok, ReqID, Val}, SD0=#state{from=From, num_r=NumR0, replies=Replies0}) -> NumR = NumR0 + 1, Replies = [Val|Replies0], SD = SD0#state{num_r=NumR,replies=Replies}, if NumR =:= ?R -> Reply = case lists:any(different(Val), Replies) of true -> Replies; false -> Val end, From ! {ReqID, ok, Reply}, {stop, normal, SD}; true -> {next_state, waiting, SD} end.
从代码中可以看出所谓强一致性就是等待全部应答,然后把应答结果组织后,一起返回去,没有达到应答数量会一直等待。
写协调更加容易:
waiting({ok, ReqID}, SD0=#state{from=From, num_w=NumW0}) -> NumW = NumW0 + 1, SD = SD0#state{num_w=NumW}, if NumW =:= ?W -> From ! {ReqID, ok}, {stop, normal, SD}; true -> {next_state, waiting, SD} end.
What About the Entry Coordinator?
Entry只是解析每一个日志,没必要使用协调器,协调器一般用在存储。
Changes to rts.erl and rts_stat_vnode
rts的模块也需要更新,主要增加fsm的代码,rts不会直接和vnode通信,交给fsm间接通信。
rts:get ----> rts_stat_vnode:get (local) /--> stat_vnode@rts1 rts:get ----> rts_get_fsm:get ----> rts_stat_vnode:get --|---> stat_vnode@rts2 \--> stat_vnode@rts3
rts:get/2函数现在也是调用get协调器然后等待结果。
get(Client, StatName) -> {ok, ReqID} = rts_get_fsm:get(Client, StatName), wait_for_reqid(ReqID, ?TIMEOUT).
写请求也经过了像是的重构。
do_write(Client, StatName, Op) -> {ok, ReqID} = rts_write_fsm:write(Client, StatName, Op), wait_for_reqid(ReqID, ?TIMEOUT). do_write(Client, StatName, Op, Val) -> {ok, ReqID} = rts_write_fsm:write(Client, StatName, Op, Val), wait_for_reqid(ReqID, ?TIMEOUT).
rts_stat_vnode
也进行了重构,使用riak_core_vnode_master:command/4
并且携带了从参数Preflist
, Msg
, Sender
和VMaster
.
Preflist: 被发送命令的vnode列表 Msg: 被发送的命令. Sender: 发送者,这里表示协调者. 主要用于vnode正确返回信息。 VMaster: VNode master的名字.
get(Preflist, ReqID, StatName) -> riak_core_vnode_master:command(Preflist, {get, ReqID, StatName}, {fsm, undefined, self()}, ?MASTER).
1.脑筋急转弯? 多个2 不是啊~?
2.CORE DUO是酷睿一代的双核版本,单核的叫CORE SOLO
3.CORE 2 DUO是酷睿二代的双核版本,单核的叫CORE 2 SOLO
4.酷睿是CORE的中文音译,就是CORE。
5.woodcrest是INTEL针对服务器工作站市场开发的CPU,FSB达到1333MB/S,L2 Cache数目将会为4MB。
6.Kentsfield是INTEL准备在2007年推出的4核心处理器。其实就是两颗双核心Conroe封装在一起而来,与此前Pentium D的设计类似。
2005年秋季的IDF上,INTEL正式宣布将采用全新构架Core的CPU来取代当前Netburst构架的Pentium 4系列,从笔记本使用的移动CPU到桌面CPU再到服务器的XEON系列,全部都将放弃现在的Netburst构架。它将衍生为移动CPU版的Merom,桌面CPU的Conroe和服务器领域的Woodcrest。旧的Netburst构架的首要任务是提升运行频率,而新的Core构架的首要的任务则是更好的集成多颗核心、以更高的效率完成任务、保持高的功耗/性能比.
按照Intel的规划,从2006年第三季度开始,台式机Core Duo将逐渐采用基于Core架构的Conroe核心,改用Socket 775接口,主流型号的前端总线提高到1066MHz FSB.
CORE DUO就是现在笔记本上面用的双核~是原来的P M核心的~
CORE 2 DUO是全新的核心~
Core(酷睿)微体系架构,其针对桌面、笔记本和服务器推出的产品代号分别是,Conroe、Merom和Woodcrest,都拥有64位处理能力,并且是双核产品。
(Conroe扣肉
Merom猫肉
Woodcrest服务器上用的)
Core 2读做“酷睿 2”或者“酷睿第二代”
1.CORNOE是核心的研发代号,就象Willamette 是P4早期核心代号,Prescott 是晚期代号一样。CORNOE是桌面级核心。
2.CORE DUO是酷睿一代的双核版本,单核的叫CORE SOLO
3.CORE 2 DUO是酷睿二代的双核版本,单核的叫CORE 2 SOLO
4.酷睿是CORE的中文音译,就是CORE。
5.woodcrest是INTEL针对服务器工作站市场开发的CPU,FSB达到1333MB/S,L2 Cache数目将会为4MB。
6.Kentsfield是INTEL准备在2007年推出的4核心处理器。其实就是两颗双核心Conroe封装在一起而来,与此前Pentium D的设计类似。
评论暂时关闭