LoginSignup
1
1

More than 5 years have passed since last update.

[WIP] Riak_Coreを読む Ring編

Last updated at Posted at 2015-04-15

Rick Coreを読む

現在Riak_Coreを調査中であり、ソースコードを読んでいる。

このエントリは、そのメモであり、まとめである。
もちろん、ただの、個人的なメモなので、間違えが当然ながら含まれているかもしれない。

Ringを読む

Ringのコンセプトやら概念

Ringとは?

Riak CoreのコンセプトにRingがある。Ringとは、データ構造であり、パーティションや、バーチャルノードの責務のデータである。Riak Coreのクラスターの全てのノードに、Ringがコピーされている。

Ringのソースコードや、周辺のコード

Ringのソースコードは以下である。

https://github.com/basho/riak_core/blob/master/src/riak_core_ring.erl
https://github.com/basho/riak_core/blob/master/src/riak_core_ring_manager.erl
https://github.com/basho/riak_core/blob/develop/include/riak_core_ring.hrl

テストコード

なんか、テストで使われているらしきデータ

良くわからん。

とりあえず、解説する。

定義されている、レコード、データ、その他

riak_core_ringモジュールで定義されている、データやらと解説するかもしれない。

chstate

-define(CHSTATE, #chstate_v2).
-record(chstate_v2, {
    nodename :: term(),          % the Node responsible for this chstate
    vclock   :: vclock:vclock() | undefined, % for this chstate object, entries are
                                 % {Node, Ctr}
    chring   :: chash:chash(),   % chash ring of {IndexAsInt, Node} mappings
    meta     :: dict() | undefined,  % dict of cluster-wide other data (primarily
                                 % bucket N-value, etc)

    clustername :: {term(), term()},
    next     :: [{integer(), term(), term(), [module()], awaiting | complete}],
    members  :: [{node(), {member_status(), vclock:vclock(), [{atom(), term()}]}}],
    claimant :: term(),
    seen     :: [{term(), vclock:vclock()}],
    rvsn     :: vclock:vclock()
}). 

とりあず、chstateのレコードが定義されている。chstateの"ch"の意味は分からない、とりあえず、状態であろう。(コメント頂きました。consistent hashingらしいですよ。)

nodenameはノードの名前、vclockはおそらくベクタークロック、chringはなんか良くわからなんけどキャッシュconsistent hashing の ring、metaは良くわからんけど、バケットやら、N-Valueが入っているらしい、clusternameはクラスターの名前?、next?わからん、たぶんこれから分かる。membersクラスターのメンバー、claimantは、スクを割り当てたり、処理を等しく分散する役割のノード、Seenとrvsnはまだ良くわからん。

%% Legacy chstate
-record(chstate, {
    nodename :: node(), % the Node responsible for this chstate
    vclock,   % for this chstate object, entries are {Node, Ctr}
    chring :: chash:chash(),   % chash ring of {IndexAsInt, Node} mappings
    meta      % dict of cluster-wide other data (primarily bucket N-value, etc)
}). 

レガシーな、chstateらしい。

-type member_status() :: joining | valid | invalid | leaving | exiting | down.

メンバーのステータス。というか、状態? join中、有効、無効、leave中、exit中、落ちた。状態遷移図書くかも。

%% type meta_entry(). Record for each entry in #chstate.meta
-record(meta_entry, {
    value,    % The value stored under this entry
    lastmod   % The last modified time of this entry, 
              %  from calendar:datetime_to_gregorian_seconds(
              %                             calendar:universal_time()), 
}).

「エントリ」のためのレコード。エントリってなんだ?

%% riak_core_ring() is the opaque data type used for partition ownership
-type riak_core_ring() :: ?CHSTATE{}.
-type chstate() :: riak_core_ring().

-type pending_change() :: {Owner :: node(),
                           NextOwner :: node(),
                           awaiting | complete}
                        | {undefined, undefined, undefined}.

-type resize_transfer() :: {{integer(),term()}, ordsets:ordset(node()), awaiting | complete}.

型周り。型は良いねー。

public API

ここから、public APIを読んで行く長い。

うーん愚直に上から読んでも良いが、まぁ、その前に、exportされている関数を見よう。

-export([all_members/1,
         all_owners/1,
         all_preflists/2,
         diff_nodes/2,
         equal_rings/2,
         fresh/0,
         fresh/1,
         fresh/2,
         get_meta/2,
         get_buckets/1,
         index_owner/2,
         my_indices/1,
         num_partitions/1,
         owner_node/1,
         preflist/2,
         random_node/1,
         random_other_index/1,
         random_other_index/2,
         random_other_node/1,
         reconcile/2,
         rename_node/3,
         responsible_index/2,
         transfer_node/3,
         update_meta/3,
         remove_meta/2]).

-export([cluster_name/1,
         legacy_ring/1,
         legacy_reconcile/2,
         upgrade/1,
         downgrade/2,
         set_tainted/1,
         check_tainted/2,
         nearly_equal/2,
         claimant/1,
         member_status/2,
         pretty_print/2,
         all_member_status/1,
         update_member_meta/5,
         clear_member_meta/3,
         get_member_meta/3,
         add_member/3,
         remove_member/3,
         leave_member/3,
         exit_member/3,
         down_member/3,
         set_member/4,
         set_member/5,
         members/2,
         set_claimant/2,
         increment_vclock/2,
         ring_version/1,
         increment_ring_version/2,
         set_pending_changes/2,
         active_members/1,
         claiming_members/1,
         ready_members/1,
         random_other_active_node/1,
         down_members/1,
         set_owner/2,
         indices/2,
         future_indices/2,
         future_ring/1,
         disowning_indices/2,
         cancel_transfers/1,
         pending_changes/1,
         next_owner/1,
         next_owner/2,
         next_owner/3,
         completed_next_owners/2,
         all_next_owners/1,
         change_owners/2,
         handoff_complete/3,
         ring_ready/0,
         ring_ready/1,
         ring_ready_info/1,
         ring_changed/2,
         set_cluster_name/2,
         reconcile_names/2,
         reconcile_members/2,
         is_primary/2,
         chash/1,
         set_chash/2,
         resize/2,
         set_pending_resize/2,
         set_pending_resize_abort/1,
         maybe_abort_resize/1,
         schedule_resize_transfer/3,
         awaiting_resize_transfer/3,
         resize_transfer_status/4,
         resize_transfer_complete/4,
         complete_resize_transfers/3,
         reschedule_resize_transfers/3,
         is_resizing/1,
         is_post_resize/1,
         is_resize_complete/1,
         resized_ring/1,
         set_resized_ring/2,
         future_index/3,
         future_index/4,
         future_index/5,
         is_future_index/4,
         future_owner/2,
         future_num_partitions/1,
         vnode_type/2,
         deletion_complete/3]).

相当多い。

読んで行こう。

名前と引数と型を読んで行く

とりあえず、型を読んで関数の意味を読んで行こう。型が無い場合は、実装を読むか、名前と引数で、推測する。

legary_ring/1

legacy_ring(#chstate{}) ->
    true;
legacy_ring(_) ->
    false.

lagacy_ringかどうか判定する。簡単。

upgrade/1

%% @doc Upgrade old ring structures to the latest format.
upgrade(Old=?CHSTATE{}) ->

まぁ、upgradeするよね。実装はあとで読む。

downgrade/2

%% @doc Downgrade the latest ring structure to a specified version.
downgrade(1,?CHSTATE{nodename=Node,
                     vclock=VC,
                     chring=Ring,
                     meta=Meta}) -> 
...

ugradeがあれば、downgradeもある。引数は2つで、第一引数がversionを取るのか。

set_tainted

set_tainted(Ring) ->
    update_meta(riak_core_ring_tainted, true, Ring).

taintedは「汚染する、腐敗させる」という意味。なんか嫌だ。

check_tainted

check_tainted(#chstate{}, _Msg) -> 
...

チェックするらしい。

nearly_equal/2

%% @doc Verify that the two rings are identical expect that metadata can
%%      differ and RingB's vclock is allowed to be equal or a direct
%%      descendant of RingA's vclock. This matches the changes that the
%%      fix-up logic may make to a ring.
-spec nearly_equal(chstate(), chstate()) -> boolean().

2つのchstate()を取り、boolean()を返す。まぁ、2つのringのメタデータが違い、vclockがequalかdescendantであるのを許可するぐらいの同一性てかね。


nearly_equal(RingA, RingB) ->
    TestVC = vclock:descends(RingB?CHSTATE.vclock, RingA?CHSTATE.vclock),
    RingA2 = RingA?CHSTATE{vclock=undefined, meta=undefined},
    RingB2 = RingB?CHSTATE{vclock=undefined, meta=undefined},
    TestRing = (RingA2 =:= RingB2),
    TestVC and TestRing.

まぁ、vlock:descends/2で、vclockのチェック、そんで、vclockとmetaをundefinedにして、等しいかチェックしている。

is_primary/2

%% @doc Determine if a given Index/Node `IdxNode' combination is a
%%      primary.
-spec is_primary(chstate(), {chash:index_as_int(), node()}) -> boolean().
is_primary(Ring, IdxNode) ->
    Owners = all_owners(Ring),
    lists:member(IdxNode, Owners).

chstate()と、{chash:index_as_int(), node()}を取り,booleanを返す。{chash:index_as_int(), node()}がprimaryであるかを判定する。

chash/1

-spec chash(chstate()) -> CHash::chash:chash().
chash(?CHSTATE{chring=CHash}) ->
    CHash.

簡単。

set_chash/2

set_chash(State, CHash) ->
    State?CHSTATE{chring=CHash}.

chashがあれば、set_chashもある。

all_membars/1 と all_membars/2

%% @doc Produce a list of all nodes that are members of the cluster
-spec all_members(State :: chstate()) -> [Node :: term()].
all_members(?CHSTATE{members=Members}) ->
    get_members(Members).

members(?CHSTATE{members=Members}, Types) ->
    get_members(Members, Types).

chstate()の全メンバーのリストを生成する。

active_members/1

%% @doc Produce a list of all active (not marked as down) cluster members
active_members(?CHSTATE{members=Members}) ->
    get_members(Members, [joining, valid, leaving, exiting]).

activeな(downしてない)クラスターのメンバーのリストを生成する。

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1