coordination free computations
play

Coordination-Free Computations Christopher Meiklejohn LASP - PowerPoint PPT Presentation

Coordination-Free Computations Christopher Meiklejohn LASP DISTRIBUTED, EVENTUALLY CONSISTENT COMPUTATIONS CHRISTOPHER MEIKLEJOHN (BASHO TECHNOLOGIES, INC.) PETER VAN ROY (UNIVERSIT CATHOLIQUE DE LOUVAIN) 2 LASP MOTIVATION 3


  1. Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 67

  2. Rovio Ad Counter Union Product Ads Riot Ad Counter Contracts Riot Ads Riot Ad Counter 68

  3. Increment Rovio Ad Counter Read Remove ≥ 50,000 Rovio Ads Rovio Ad Counter Ads Union Product Filter Ads Contracts Riot Ad Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter 69

  4. Ads Ads Union Product Filter Ads With Contracts Contracts Lasp Operation Contracts User-Maintained CRDT 70

  5. Read Ads Ads Product Filter Ads With Contracts Contracts Lasp Operation Contracts 71

  6. Counter1 Counter2 Counter3 Read Counter1 Counter2 Counter3 Ads Ads Filter With Contracts Contracts Counter1 Counter2 Counter3 Lasp Operation User-Maintained CRDT Counter1 Counter2 Counter3 Lasp-Maintained CRDT 72

  7. Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 73

  8. Increment Rovio Ad Counter Read Remove ≥ 50,000 Rovio Ads Rovio Ad Counter Ads Union Product Ads Contracts Riot Ad Counter Lasp Operation Contracts Riot Ads 74

  9. Counter1 Counter2 Counter3 Read Remove Read 50,000 Rovio Ads Counter1 Counter2 Counter3 Ads Ads Union Product Filter Ads With Contracts Contracts Counter1 Counter2 Counter3 Lasp Operation Contracts Riot Ads User-Maintained CRDT Counter1 Counter2 Counter3 Lasp-Maintained CRDT 75

  10. INFORMATION FLOW: MONOTONIC METADATA TO PREVENT DUPLICATE PROPAGATION 76

  11. AD COUNTER EXAMPLE CODE 77

  12. %% @doc Client process; standard recursive looping server. client(Id, AdsWithContracts, PreviousValue) -> receive view_ad -> %% Get current ad list. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts, PreviousValue), AdList = riak_dt_orset:value(AdList0), case length(AdList) of 0 -> %% No advertisements left to display; ignore %% message. client(Id, AdsWithContracts, AdList0); _ -> %% Select a random advertisement from the list of %% active advertisements. {#ad{counter=Ad}, _} = lists:nth( random:uniform(length(AdList)), AdList), %% Increment it. {ok, _} = lasp:update(Ad, increment, Id), lager:info("Incremented ad counter: ~p", [Ad]), client(Id, AdsWithContracts, AdList0) end end.

  13. %% @doc Server functions for the advertisement counter. After 5 views, %% disable the advertisement. %% server({#ad{counter=Counter}=Ad, _}, Ads) -> %% Blocking threshold read for 5 advertisement impressions. {ok, _} = lasp:read(Counter, 5), %% Remove the advertisement. {ok, _} = lasp:update(Ads, {remove, Ad}, Ad), lager:info("Removing ad: ~p", [Ad]).

  14. %% Generate a series of unique identifiers. %% Compute the Cartesian product of both ads and contracts. RovioAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), {ok, AdsContracts} = lasp:declare(?SET), lager:info("Rovio Ad Identifiers are: ~p", [RovioAdIds]), ok = lasp:product(Ads, Contracts, AdsContracts), TriforkAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), %% Filter items by join on item it. lager:info("Trifork Ad Identifiers are: ~p", [TriforkAdIds]), {ok, AdsWithContracts} = lasp:declare(?SET), FilterFun = fun({#ad{id=Id1}, #contract{id=Id2}}) -> Ids = RovioAdIds ++ TriforkAdIds, Id1 =:= Id2 lager:info("Ad Identifiers are: ~p", [Ids]), end, ok = lasp:filter(AdsContracts, FilterFun, AdsWithContracts), %% Generate Rovio's advertisements. {ok, RovioAds} = lasp:declare(?SET), %% Launch a series of client processes, each of which is responsible lists:map(fun(Id) -> %% for displaying a particular advertisement. %% Generate a G-Counter. {ok, CounterId} = lasp:declare(?COUNTER), %% Generate a OR-set for tracking clients. %% Add it to the advertisement set. {ok, Clients} = lasp:declare(?SET), {ok, _} = lasp:update(RovioAds, {add, #ad{id=Id, counter=CounterId}}, %% Each client takes the full list of ads when it starts, and reads undefined) %% from the variable store. lists:map(fun(Id) -> end, RovioAdIds), ClientPid = spawn_link(?MODULE, client, [Id, AdsWithContracts, undefined]), %% Generate Trifork's advertisements. {ok, _} = lasp:update(Clients, {ok, TriforkAds} = lasp:declare(?SET), {add, ClientPid}, lists:map(fun(Id) -> undefined) %% Generate a G-Counter. end, lists:seq(1,5)), {ok, CounterId} = lasp:declare(?COUNTER), %% Add it to the advertisement set. %% Launch a server process for each advertisement, which will block {ok, _} = lasp:update(TriforkAds, %% until the advertisement should be disabled. {add, #ad{id=Id, counter=CounterId}}, undefined) %% Create a OR-set for the server list. {ok, Servers} = lasp:declare(?SET), end, TriforkAdIds), %% Get the current advertisement list. %% Union ads. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts), {ok, Ads} = lasp:declare(?SET), AdList = riak_dt_orset:value(AdList0), ok = lasp:union(RovioAds, TriforkAds, Ads), %% For each advertisement, launch one server for tracking it's %% For each identifier, generate a contract. %% impressions and wait to disable. {ok, Contracts} = lasp:declare(?SET), lists:map(fun(Ad) -> lists:map(fun(Id) -> ServerPid = spawn_link(?MODULE, server, [Ad, Ads]), {ok, _} = lasp:update(Contracts, {ok, _} = lasp:update(Servers, {add, #contract{id=Id}}, {add, ServerPid}, undefined) undefined) end, Ids), end, AdList),

  15. %% Generate a series of unique identifiers. %% Compute the Cartesian product of both ads and contracts. RovioAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), {ok, AdsContracts} = lasp:declare(?SET), lager:info("Rovio Ad Identifiers are: ~p", [RovioAdIds]), ok = lasp:product(Ads, Contracts, AdsContracts), TriforkAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), %% Filter items by join on item it. lager:info("Trifork Ad Identifiers are: ~p", [TriforkAdIds]), {ok, AdsWithContracts} = lasp:declare(?SET), FilterFun = fun({#ad{id=Id1}, #contract{id=Id2}}) -> Ids = RovioAdIds ++ TriforkAdIds, Id1 =:= Id2 lager:info("Ad Identifiers are: ~p", [Ids]), end, ok = lasp:filter(AdsContracts, FilterFun, AdsWithContracts), %% Generate Rovio's advertisements. {ok, RovioAds} = lasp:declare(?SET), %% Launch a series of client processes, each of which is responsible lists:map(fun(Id) -> %% for displaying a particular advertisement. %% Generate a G-Counter. {ok, CounterId} = lasp:declare(?COUNTER), %% Generate a OR-set for tracking clients. %% Add it to the advertisement set. {ok, Clients} = lasp:declare(?SET), {ok, _} = lasp:update(RovioAds, {add, #ad{id=Id, counter=CounterId}}, %% Each client takes the full list of ads when it starts, and reads undefined) %% from the variable store. lists:map(fun(Id) -> end, RovioAdIds), ClientPid = spawn_link(?MODULE, client, [Id, AdsWithContracts, undefined]), %% Generate Trifork's advertisements. {ok, _} = lasp:update(Clients, {ok, TriforkAds} = lasp:declare(?SET), {add, ClientPid}, lists:map(fun(Id) -> undefined) %% Generate a G-Counter. end, lists:seq(1,5)), {ok, CounterId} = lasp:declare(?COUNTER), %% Add it to the advertisement set. %% Launch a server process for each advertisement, which will block {ok, _} = lasp:update(TriforkAds, %% until the advertisement should be disabled. {add, #ad{id=Id, counter=CounterId}}, undefined) %% Create a OR-set for the server list. {ok, Servers} = lasp:declare(?SET), end, TriforkAdIds), %% Get the current advertisement list. %% Union ads. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts), {ok, Ads} = lasp:declare(?SET), AdList = riak_dt_orset:value(AdList0), ok = lasp:union(RovioAds, TriforkAds, Ads), %% For each advertisement, launch one server for tracking it's %% For each identifier, generate a contract. %% impressions and wait to disable. {ok, Contracts} = lasp:declare(?SET), lists:map(fun(Ad) -> lists:map(fun(Id) -> ServerPid = spawn_link(?MODULE, server, [Ad, Ads]), {ok, _} = lasp:update(Contracts, {ok, _} = lasp:update(Servers, {add, #contract{id=Id}}, {add, ServerPid}, undefined) undefined) end, Ids), end, AdList),

  16. %% Generate a series of unique identifiers. %% Compute the Cartesian product of both ads and contracts. RovioAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), {ok, AdsContracts} = lasp:declare(?SET), lager:info("Rovio Ad Identifiers are: ~p", [RovioAdIds]), ok = lasp:product(Ads, Contracts, AdsContracts), TriforkAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), %% Filter items by join on item it. lager:info("Trifork Ad Identifiers are: ~p", [TriforkAdIds]), {ok, AdsWithContracts} = lasp:declare(?SET), FilterFun = fun({#ad{id=Id1}, #contract{id=Id2}}) -> Ids = RovioAdIds ++ TriforkAdIds, Id1 =:= Id2 lager:info("Ad Identifiers are: ~p", [Ids]), end, ok = lasp:filter(AdsContracts, FilterFun, AdsWithContracts), %% Generate Rovio's advertisements. {ok, RovioAds} = lasp:declare(?SET), %% Launch a series of client processes, each of which is responsible lists:map(fun(Id) -> %% for displaying a particular advertisement. %% Generate a G-Counter. {ok, CounterId} = lasp:declare(?COUNTER), %% Generate a OR-set for tracking clients. %% Add it to the advertisement set. {ok, Clients} = lasp:declare(?SET), {ok, _} = lasp:update(RovioAds, {add, #ad{id=Id, counter=CounterId}}, %% Each client takes the full list of ads when it starts, and reads undefined) %% from the variable store. lists:map(fun(Id) -> end, RovioAdIds), ClientPid = spawn_link(?MODULE, client, [Id, AdsWithContracts, undefined]), %% Generate Trifork's advertisements. {ok, _} = lasp:update(Clients, {ok, TriforkAds} = lasp:declare(?SET), {add, ClientPid}, lists:map(fun(Id) -> undefined) %% Generate a G-Counter. end, lists:seq(1,5)), {ok, CounterId} = lasp:declare(?COUNTER), %% Add it to the advertisement set. %% Launch a server process for each advertisement, which will block {ok, _} = lasp:update(TriforkAds, %% until the advertisement should be disabled. {add, #ad{id=Id, counter=CounterId}}, undefined) %% Create a OR-set for the server list. {ok, Servers} = lasp:declare(?SET), end, TriforkAdIds), %% Get the current advertisement list. %% Union ads. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts), {ok, Ads} = lasp:declare(?SET), AdList = riak_dt_orset:value(AdList0), ok = lasp:union(RovioAds, TriforkAds, Ads), %% For each advertisement, launch one server for tracking it's %% For each identifier, generate a contract. %% impressions and wait to disable. {ok, Contracts} = lasp:declare(?SET), lists:map(fun(Ad) -> lists:map(fun(Id) -> ServerPid = spawn_link(?MODULE, server, [Ad, Ads]), {ok, _} = lasp:update(Contracts, {ok, _} = lasp:update(Servers, {add, #contract{id=Id}}, {add, ServerPid}, undefined) undefined) end, Ids), end, AdList),

  17. %% Generate a series of unique identifiers. %% Compute the Cartesian product of both ads and contracts. RovioAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), {ok, AdsContracts} = lasp:declare(?SET), lager:info("Rovio Ad Identifiers are: ~p", [RovioAdIds]), ok = lasp:product(Ads, Contracts, AdsContracts), TriforkAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), %% Filter items by join on item it. lager:info("Trifork Ad Identifiers are: ~p", [TriforkAdIds]), {ok, AdsWithContracts} = lasp:declare(?SET), FilterFun = fun({#ad{id=Id1}, #contract{id=Id2}}) -> Ids = RovioAdIds ++ TriforkAdIds, Id1 =:= Id2 lager:info("Ad Identifiers are: ~p", [Ids]), end, ok = lasp:filter(AdsContracts, FilterFun, AdsWithContracts), %% Generate Rovio's advertisements. {ok, RovioAds} = lasp:declare(?SET), %% Launch a series of client processes, each of which is responsible lists:map(fun(Id) -> %% for displaying a particular advertisement. %% Generate a G-Counter. {ok, CounterId} = lasp:declare(?COUNTER), %% Generate a OR-set for tracking clients. %% Add it to the advertisement set. {ok, Clients} = lasp:declare(?SET), {ok, _} = lasp:update(RovioAds, {add, #ad{id=Id, counter=CounterId}}, %% Each client takes the full list of ads when it starts, and reads undefined) %% from the variable store. lists:map(fun(Id) -> end, RovioAdIds), ClientPid = spawn_link(?MODULE, client, [Id, AdsWithContracts, undefined]), %% Generate Trifork's advertisements. {ok, _} = lasp:update(Clients, {ok, TriforkAds} = lasp:declare(?SET), {add, ClientPid}, lists:map(fun(Id) -> undefined) %% Generate a G-Counter. end, lists:seq(1,5)), {ok, CounterId} = lasp:declare(?COUNTER), %% Add it to the advertisement set. %% Launch a server process for each advertisement, which will block {ok, _} = lasp:update(TriforkAds, %% until the advertisement should be disabled. {add, #ad{id=Id, counter=CounterId}}, undefined) %% Create a OR-set for the server list. {ok, Servers} = lasp:declare(?SET), end, TriforkAdIds), %% Get the current advertisement list. %% Union ads. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts), {ok, Ads} = lasp:declare(?SET), AdList = riak_dt_orset:value(AdList0), ok = lasp:union(RovioAds, TriforkAds, Ads), %% For each advertisement, launch one server for tracking it's %% For each identifier, generate a contract. %% impressions and wait to disable. {ok, Contracts} = lasp:declare(?SET), lists:map(fun(Ad) -> lists:map(fun(Id) -> ServerPid = spawn_link(?MODULE, server, [Ad, Ads]), {ok, _} = lasp:update(Contracts, {ok, _} = lasp:update(Servers, {add, #contract{id=Id}}, {add, ServerPid}, undefined) undefined) end, Ids), end, AdList),

  18. %% Generate a series of unique identifiers. %% Compute the Cartesian product of both ads and contracts. RovioAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), {ok, AdsContracts} = lasp:declare(?SET), lager:info("Rovio Ad Identifiers are: ~p", [RovioAdIds]), ok = lasp:product(Ads, Contracts, AdsContracts), TriforkAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), %% Filter items by join on item it. lager:info("Trifork Ad Identifiers are: ~p", [TriforkAdIds]), {ok, AdsWithContracts} = lasp:declare(?SET), FilterFun = fun({#ad{id=Id1}, #contract{id=Id2}}) -> Ids = RovioAdIds ++ TriforkAdIds, Id1 =:= Id2 lager:info("Ad Identifiers are: ~p", [Ids]), end, ok = lasp:filter(AdsContracts, FilterFun, AdsWithContracts), %% Generate Rovio's advertisements. {ok, RovioAds} = lasp:declare(?SET), %% Launch a series of client processes, each of which is responsible lists:map(fun(Id) -> %% for displaying a particular advertisement. %% Generate a G-Counter. {ok, CounterId} = lasp:declare(?COUNTER), %% Generate a OR-set for tracking clients. %% Add it to the advertisement set. {ok, Clients} = lasp:declare(?SET), {ok, _} = lasp:update(RovioAds, {add, #ad{id=Id, counter=CounterId}}, %% Each client takes the full list of ads when it starts, and reads undefined) %% from the variable store. lists:map(fun(Id) -> end, RovioAdIds), ClientPid = spawn_link(?MODULE, client, [Id, AdsWithContracts, undefined]), %% Generate Trifork's advertisements. {ok, _} = lasp:update(Clients, {ok, TriforkAds} = lasp:declare(?SET), {add, ClientPid}, lists:map(fun(Id) -> undefined) %% Generate a G-Counter. end, lists:seq(1,5)), {ok, CounterId} = lasp:declare(?COUNTER), %% Add it to the advertisement set. %% Launch a server process for each advertisement, which will block {ok, _} = lasp:update(TriforkAds, %% until the advertisement should be disabled. {add, #ad{id=Id, counter=CounterId}}, undefined) %% Create a OR-set for the server list. {ok, Servers} = lasp:declare(?SET), end, TriforkAdIds), %% Get the current advertisement list. %% Union ads. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts), {ok, Ads} = lasp:declare(?SET), AdList = riak_dt_orset:value(AdList0), ok = lasp:union(RovioAds, TriforkAds, Ads), %% For each advertisement, launch one server for tracking it's %% For each identifier, generate a contract. %% impressions and wait to disable. {ok, Contracts} = lasp:declare(?SET), lists:map(fun(Ad) -> lists:map(fun(Id) -> ServerPid = spawn_link(?MODULE, server, [Ad, Ads]), {ok, _} = lasp:update(Contracts, {ok, _} = lasp:update(Servers, {add, #contract{id=Id}}, {add, ServerPid}, undefined) undefined) end, Ids), end, AdList),

  19. AD COUNTER DISTRIBUTION 85

  20. Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 86

  21. Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 87

  22. Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 88

  23. Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 89

  24. DISTRIBUTION BOUNDARIES: ARBITRARY ALLOWS COMPOSITION OF ENTIRE SYSTEM 90

  25. MATERIALIZED VIEWS 91

  26. MATERIALIZED VIEWS: INCREMENTALLY UPDATING, DELTA PROPAGATION SCHEMA BASED OR DYNAMIC; 2I IN RIAK 92

  27. DATABASE AS STREAM OF UPDATES 93

  28. K1 K2 K3 K1 K2 Riak 94

  29. RS1 K1 K2 K3 K1 K2 RS2 Riak RS3 95

  30. K1 K1 RS1 K1 K2 K3 K1 K2 K2 K2 RS2 Riak K3 RS3 96

  31. K1 K1 N1 N3 N2 K1 K2 K3 K1 K2 K2 K2 RS2 Riak K3 RS3 97

  32. COMPOSE PROGRAMS 98

  33. K1 K1 N1 N3 N2 K1 K2 K3 K1 K2 K2 K2 RS2 Riak K3 RS3 Lasp Stream Processor Template 99

  34. K1 K1 N1 N3 N2 K1 K2 K3 K1 K2 K2 K2 RS2 Riak K3 RS3 Lasp All Objects Program Lasp Stream Processor Template 100

Recommend


More recommend