80
1 C B DePue III Author Project Implementing Redis In Erlang.graffle File Thu Mar 29 2012 Date Edis REdis: Implementing Redis in Erlang A step-by-step walkthrough

Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

Embed Size (px)

Citation preview

Page 1: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

1C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

REdis: Implementing Redis in ErlangA step-by-step walkthrough

Page 2: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

2C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

2

Edis: Implementing Redis in ErlangA step-by-step walkthrough

Page 3: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

3C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

My Background

• Microsoft Visual Studio• Visto Corporation• Founded Inaka • Moved to Argentina 2008

@chaddepue / cdepue

Page 4: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

4C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Inaka Overview

• Started in 2009• iPhone/Android Apps• Erlang Systems• Ruby/Rails

Page 5: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

5C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Our Vision

• Remote Startup Incubator• Focus on New Media• Social Media• Big Data

Page 6: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

6C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Our Apps

• MTV WatchWith• MovieNightOut• Whisper• Campus Sentinel

Page 7: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

7C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

My Goals For This Talk

• See a server app you know in Erlang• Walk through gen_tcp/gen_fsm• See the Redis API implementation• See how to extend Edis

Page 8: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

8C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

What are Redis and Edis?

Redis - a C-based fast in-memory, disk-backed key/value database

Edis - an Erlang-based, leveldb-backed key/value store that speaks the Redis protocol

Page 9: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

9C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

What specifically is Edis?

• Uses gen_tcp• Uses gen_fsm• Uses LevelDB• Implements full Redis command set• Respects Redis algorithms

Edis - an Erlang-based server that...

Page 10: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

10C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

What makes Redis worth copying?

Page 11: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

11C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

3 things...

• Speed• Expressivity of the command set• Ease of Deployment

Page 12: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

12C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Speed

"Raw speed is bound to queries per watt. Energy is a serious problem, not just for the environment, but also cost-wise. More computers running to serve your 1000 requests per second, the bigger your monthly bill."

Salvatore Sanfilippo

Page 13: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

13C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Expressive Command Set

Key/ValueHashesListsSetsSorted SetsPublish/SubscribeTransactions

SET/GETHSETNXRPOP/LPOPSUNION/SPOPZADD/ZRANGESUBSCRIBE/PUBLISHMULTI/EXEC

Command Group Selected Commands

Page 14: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

14C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Expressive Command Set 2

RPOPLPUSH

1 , 2 , 7, 10work_queue

Page 15: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

15C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Expressive Command Set 3

RPOPLPUSH

1 , 2 , 7, 10work_queue

run_queue 18

Page 16: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

16C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Expressive Command Set 4

RPOPLPUSH

1 , 2 , 7work_queue

run_queue 10, 18

Page 17: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

17C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Easy Deployment

$ redis-server

$ redis-cli

Page 18: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

18C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Traded for ...

• "Weak" Persistence - not a great disk-backed DB - data must fit in-memory

* great article by Salvatore on Mondayabout AOF and RDB options

Page 19: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

19C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Traded for ... 2

• Lack of Expandability*

*lua scripting is here in 2.6… but it's blocking the main thread!?

Page 20: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

20C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Comparisons

RedisIncredibly FastAmazing Command SetGuarantees in ~ 1sLimited ExtensibilityData can't exceed RAM

EdisSlowAlmost The Same SetGuaranteed PersistanceExtensibleData can exceed RAM

Page 21: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

21C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Three Topics

Implementing the Redis Protocol

Measuring Edis Performance

Extending Edis

Page 22: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

22C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Part I

Protocol

Page 23: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

23C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Redis protocol

clientredis:6379

*3\r\n

"SET lang erlang"

$3\r\n

set\r\n

$4\r\n

$5\r\n

lang\r\n

erlang\r\n

(# of params)

(length of #1)

(command)

(length of #2)

(data)

(length of #3)

(data)

OK\r\n(response)

Page 24: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

24C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

State Machine - Client

S1

S2 S3

*<args>

arg_size

command_start

$<size> command_name

S4

argument

<command>

$<size>

<argument>

S5

run

<last argument>

Page 25: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

25C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Application Structure

edis_sup

edis_pubsub_sup edis_client_sup* edis_listener_sup edis_db_sup

* simple_one_for_one

Page 26: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

26C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Ready for connections

edis_sup

edis_pubsub_sup edis_client_sup edis_listener_sup edis_db_sup

edis-client-mgr-1 edis-client-listener-6379

edis-db-1edis-db-1edis-db-1

Page 27: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

27C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Ready for connections 2

edis_sup

edis_pubsub_sup edis_client_sup edis_listener_sup edis_db_sup

edis-client-mgr-1 edis-client-listener-6379

edis-db-1edis-db-1edis-db-1

Page 28: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

28C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_listener_sup.erl

37 init([]) ->38 {MinPort, MaxPort} = edis_config:get(listener_port_range),39 Listeners =40 [{list_to_atom("edis-listener-" ++ integer_to_list(I)),41 {edis_listener, start_link, [I]}, permanent, brutal_kill,42 worker, [edis_listener]}43 || I <- lists:seq(MinPort, MaxPort)],44 {ok, {{one_for_one, 5, 10}, Listeners}}.

Page 29: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

29C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_listener_sup.erl 2

37 init([]) ->38 {MinPort, MaxPort} = edis_config:get(listener_port_range),39 Listeners =40 [{list_to_atom("edis-listener-" ++ integer_to_list(I)),41 {edis_listener, start_link, [I]}, permanent, brutal_kill,42 worker, [edis_listener]}43 || I <- lists:seq(MinPort, MaxPort)],44 {ok, {{one_for_one, 5, 10}, Listeners}}.

Page 30: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

30C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_listener.erl init(Port)

53 init(Port) -> 54 case gen_tcp:listen(Port, ?TCP_OPTIONS) of 55 {ok, Socket} -> 56 {ok, Ref} = prim_inet:async_accept(Socket, -1), 57 {ok, #state{listener = Socket, 58 acceptor = Ref}}; 59 {error, Reason} -> 60 {stop, Reason} 61 end. 62

Page 31: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

31C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_listener.erl init(Port) 2

53 init(Port) -> 54 case gen_tcp:listen(Port, ?TCP_OPTIONS) of 55 {ok, Socket} -> 56 {ok, Ref} = prim_inet:async_accept(Socket, -1), 57 {ok, #state{listener = Socket, 58 acceptor = Ref}}; 59 {error, Reason} -> 60 {stop, Reason} 61 end. 62

Page 32: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

32C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_listener.erl handle_info/2 76 handle_info({inet_async, ListSock, Ref, {ok, CliSocket}}, 77 #state{listener = ListSock, acceptor = Ref} = State) -> .. 91 %% New client connected… 92 ?DEBUG("Client ~p starting...~n", [PeerPort]), 93 {ok, Pid} = edis_client_sup:start_client(), 94 95 ok = gen_tcp:controlling_process(CliSocket, Pid), 96 97 %% Instruct the new FSM that it owns the socket. 98 ok = edis_client:set_socket(Pid, CliSocket), 99 100 %% Tell the network driver we are ready for another connection101 NewRef = prim_inet:async_accept(ListSock, -1)...110 {noreply, State#state{acceptor = NewRef}}

Page 33: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

33C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

… Connection Established

edis_sup

edis_pubsub_sup edis_client_sup edis_listener_sup edis_db_sup

edis-client-mgr-1 edis-client-listener-6379

edis-db-1edis-db-1edis-db-1

Page 34: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

34C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

… Connection Established 2

edis_sup

edis_pubsub_sup edis_client_sup edis_listener_sup edis_db_sup

edis-client-mgr-1 edis-client-listener-6379

edis-db-1edis-db-1edis-db-1

Page 35: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

35C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

… Connection Established 3edis_sup

edis_pubsub_sup

edis_client_sup

edis_listener_sup edis_db_sup

edis-client-mgr-1

edis-client-listener-6379 edis-db-1edis-db-1edis-db-1

edis_client

edis_client

edis-client-mgr-1

<0.114.0>

<0.115.0>edis_command_runner

Page 36: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

36C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_client.erl 64 socket({socket_ready, Socket}, State) -> 65 % Now we own the socket 66 PeerPort = inet:peername(Socket), 67 68 ok = inet:setopts(Socket, [{active, once}, 69 {packet, line}, binary]), 70 _ = erlang:process_flag(trap_exit, true), 71 {ok, CmdRunner} = edis_command_runner:start_link(Socket), 72 {next_state, command_start, 73 State#state{socket = Socket, 74 peerport = PeerPort, 75 command_runner = CmdRunner}, hibernate};

Page 37: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

37C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_client.erl 1 64 socket({socket_ready, Socket}, State) -> 65 % Now we own the socket 66 PeerPort = inet:peername(Socket), 67 68 ok = inet:setopts(Socket, [{active, once}, 69 {packet, line}, binary]), 70 _ = erlang:process_flag(trap_exit, true), 71 {ok, CmdRunner} = edis_command_runner:start_link(Socket), 72 {next_state, command_start, 73 State#state{socket = Socket, 74 peerport = PeerPort, 75 command_runner = CmdRunner}, hibernate};

Page 38: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

38C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_client.erl 1.2 64 socket({socket_ready, Socket}, State) ->

{active, once},{packet, line}

Page 39: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

39C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

… Connection Established 4edis_sup

edis_pubsub_sup

edis_client_sup

edis_listener_sup edis_db_sup

edis-client-mgr-1

edis-client-listener-6379 edis-db-1edis-db-1edis-db-1

edis_client

edis_client

edis-client-mgr-1

<0.114.0>

<0.115.0>edis_command_runner

Page 40: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

40C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

… Connection Established 5edis_sup

edis_pubsub_sup

edis_client_sup

edis_listener_sup edis_db_sup

edis-client-mgr-1

edis-client-listener-6379 edis-db-1edis-db-1edis-db-1

edis_client

edis_client(gen_fsm)

edis-client-mgr-1

<0.114.0>

<0.115.0>edis_command_runner

Page 41: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

41C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_client.erl 2 64 socket({socket_ready, Socket}, State) -> 65 % Now we own the socket 66 PeerPort = inet:peername(Socket), 67 68 ok = inet:setopts(Socket, [{active, once}, 69 {packet, line}, binary]), 70 _ = erlang:process_flag(trap_exit, true), 71 {ok, CmdRunner} = edis_command_runner:start_link(Socket), 72 {next_state, command_start, 73 State#state{socket = Socket, 74 peerport = PeerPort, 75 command_runner = CmdRunner}, hibernate};

Page 42: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

42C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_client.erl 3 64 socket({socket_ready, Socket}, State) ->

72 {next_state, command_start, 73 State#state{socket = Socket, 74 peerport = PeerPort, 75 command_runner = CmdRunner}, hibernate};

{next_state, StateName, State};

Page 43: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

43C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_client.erl 4 64 socket({socket_ready, Socket}, State) ->

72 {next_state, command_start, 73 State#state{socket = Socket, 74 peerport = PeerPort, 75 command_runner = CmdRunner}, hibernate};

{next_state, StateName, State};

Page 44: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

44C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_client.erl 5

gen_fsm:send_event(<Pid>,message).

edis_client:StateName(message,State).

Page 45: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

45C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_client.erl 6

edis_client:command_start({data,Data},State}).

Page 46: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

46C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

State Machine - Client 2

S1

S2 S3

*<args>

arg_size

command_start

$<size> command_name

S4

argument

<command>

$<size>

<argument>

S5

run

<last argument>

*DBG* <0.104.0> got {tcp,#Port<0.3714>,<<"*3\r\n">>} in state command_start*DBG* <0.104.0> switched to state arg_size

Page 47: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

47C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

State Machine - Client 3

S1

S2 S3

*<args>

arg_size

command_start

$<size> command_name

S4

argument

<command>

$<size>

<argument>

S5

run

<last argument>

*DBG* <0.104.0> got {tcp,#Port<0.3714>,<<"$3\r\n">>} in state arg_size*DBG* <0.104.0> switched to state command_name

Page 48: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

48C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

State Machine - Client 4

S1

S2 S3

*<args>

arg_size

command_start

$<size> command_name

S4

argument

<command>

$<size>

<argument>

S5

run

<last argument>

*DBG* <0.104.0> got {tcp,#Port<0.3714>,<<"set\r\n">>} in state command_name*DBG* <0.104.0> switched to state arg_size

Page 49: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

49C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

State Machine - Client 5

S1

S2 S3

*<args>

arg_size

command_start

$<size> command_name

S4

argument

<command>

$<size>

<argument>

S5

run

<last argument>

*DBG* <0.104.0> got {tcp,#Port<0.3714>,<<"$4\r\n">>} in state arg_size*DBG* <0.104.0> switched to state argument

Page 50: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

50C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

State Machine - Client 6

S1

S2 S3

*<args>

arg_size

command_start

$<size> command_name

S4

argument

<command>

$<size>

<argument>

S5

run

<last argument>

*DBG* <0.104.0> got {tcp,#Port<0.3714>,<<"lang\r\n">>} in state argument*DBG* <0.104.0> switched to state arg_size

Page 51: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

51C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

State Machine - Client 7

S1

S2 S3

*<args>

arg_size

command_start

$<size> command_name

S4

argument

<command>

$<size>

<argument>

S5

run

<last argument>

*DBG* <0.104.0> got {tcp,#Port<0.3714>,<<"$5\r\n">>} in state arg_size*DBG* <0.104.0> switched to state argument

Page 52: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

52C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

State Machine - Client 8

S1

S2 S3

*<args>

arg_size

command_start

$<size> command_name

S4

argument

<command>

$<size>

<argument>

S5

(run)

<last argument>

*DBG* <0.104.0> got {tcp,#Port<0.3714>,<<"erlang\r\n">>} in state argument*DBG* <0.104.0> switched to state command_start

Page 53: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

53C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Tracing the states 8

*DBG* <0.105.0> got cast {run,<<"SET">>,[<<"lang">>,<<"erlang">>]}*DBG* <0.105.0> new state {state,#Port<0.3714>, 'edis-db-0',0,56068,true,undefined,[],undefined}

Page 54: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

54C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_client.erl 8

120 edis_command_runner:run(State#state.command_runner, 121 edis_util:upper(Command), []),122 {next_state, command_start, State, hibernate}

Page 55: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

55C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

State Machine - Runner

S1 S2

S3

SUBSCRIBE

pubsubrunning

queuingEXEC

UNSUBSCRIBE

MULTI

SUBSCRIBE

S4quit

QUIT

QUIT

QUIT

Page 56: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

56C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

command_runner 87 handle_cast({run, Cmd, Args}, State) -> 88 try 89 OriginalCommand = #edis_command{cmd = Cmd, 90 db = State#state.db_index, 91 args = Args}, 92 93 Command = parse_command(OriginalCommand), 94 95 ok = edis_db_monitor:notify(OriginalCommand), 96 97 case {State#state.multi_queue, State#state.subscriptions} of 98 {undefined, undefined} -> run(Command, State); 99 {undefined, _InPubSub} -> pubsub(Command, State); 100 {_InMulti, undefined} -> queue(Command, State); 101 {_InMulti, _InPubSub} -> throw(invalid_context) 102 end 103 catch

Page 57: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

57C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

command_runner 2 87 handle_cast({run, Cmd, Args}, State) -> 88 try 89 OriginalCommand = #edis_command{cmd = Cmd, 90 db = State#state.db_index, 91 args = Args}, 92 93 Command = parse_command(OriginalCommand), 94 95 ok = edis_db_monitor:notify(OriginalCommand), 96 97 case {State#state.multi_queue, State#state.subscriptions} of 98 {undefined, undefined} -> run(Command, State); 99 {undefined, _InPubSub} -> pubsub(Command, State); 100 {_InMulti, undefined} -> queue(Command, State); 101 {_InMulti, _InPubSub} -> throw(invalid_context) 102 end 103 catch

Page 58: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

58C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

command_runner 3 87 handle_cast({run, Cmd, Args}, State) -> 88 try 89 OriginalCommand = #edis_command{cmd = Cmd, 90 db = State#state.db_index, 91 args = Args}, 92 93 Command = parse_command(OriginalCommand), 94 95 ok = edis_db_monitor:notify(OriginalCommand), 96 97 case {State#state.multi_queue, State#state.subscriptions} of 98 {undefined, undefined} -> run(Command, State); 99 {undefined, _InPubSub} -> pubsub(Command, State); 100 {_InMulti, undefined} -> queue(Command, State); 101 {_InMulti, _InPubSub} -> throw(invalid_context) 102 end 103 catch

Page 59: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

59C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_db

67 run(Db, Command, Timeout) -> 68 try gen_server:call(Db, Command, Timeout) of 69 ok -> ok; 70 {ok, Reply} -> Reply; 71 {error, Error} -> 72 throw(Error) 73 catch 74 _:{timeout, _} -> 75 throw(timeout) 76 end.

Page 60: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

60C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_db 2

67 run(Db, Command, Timeout) -> 68 try gen_server:call(Db, Command, Timeout) of 69 ok -> ok; 70 {ok, Reply} -> Reply; 71 {error, Error} -> 72 throw(Error) 73 catch 74 _:{timeout, _} -> 75 throw(timeout) 76 end.

Page 61: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

61C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_db 3

214 handle_call(#edis_command{cmd = <<"MSET">>, args = KVs}, 215 _From, State) -> 216 Reply = 217 (State#state.backend_mod):write( 218 State#state.backend_ref, 219 [{put, Key, 220 #edis_item{key = Key, encoding = raw, 221 type = string, value = Value}} || {Key, Value} <- KVs]), 222 {reply, Reply, stamp([K || {K, _} <- KVs], write, State)};

Page 62: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

62C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_db 4

214 handle_call(#edis_command{cmd = <<"MSET">>, args = KVs}, 215 _From, State) -> 216 Reply = 217 (State#state.backend_mod):write( 218 State#state.backend_ref, 219 [{put, Key, 220 #edis_item{key = Key, encoding = raw, 221 type = string, value = Value}} || {Key, Value} <- KVs]), 222 {reply, Reply, stamp([K || {K, _} <- KVs], write, State)};

Page 63: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

63C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_eleveldb_backend.erl

35 write(#ref{db = Db}, Actions) ->36 ParseAction = fun({put, Key, Item}) -> 37 {put, Key, erlang:term_to_binary(Item)};38 (Action) -> Action39 end,40 eleveldb:write(Db, lists:map(ParseAction, Actions), []).41

Page 64: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

64C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_eleveldb_backend.erl 2

35 write(#ref{db = Db}, Actions) ->36 ParseAction = fun({put, Key, Item}) -> 37 {put, Key, erlang:term_to_binary(Item)};38 (Action) -> Action39 end,40 eleveldb:write(Db, lists:map(ParseAction, Actions), []).41

Page 65: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

65C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_command_runner.erl l

700 run(C = #edis_command{result_type = ResType, 701 timeout = Timeout, hooks = Hooks}, State) -> 702 Res = edis_db:run(State#state.db, C);

Page 66: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

66C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

edis_command_runner.erl l 2

716 case ResType of 717 ok -> tcp_ok(State); 718 string -> tcp_string(Res, State); 719 bulk -> tcp_bulk(Res, State); 720 multi_bulk -> tcp_multi_bulk(Res, State); 721 number -> tcp_number(Res, State); 722 boolean -> tcp_boolean(Res, State); 723 float -> tcp_float(Res, State); 724 sort -> tcp_sort(Res, State); 725 zrange -> 726 [_Key, _Min, _Max, ShowScores, Limit] = C#edis_command.args, 727 tcp_zrange(Res, ShowScores, Limit, State) 728 end.

Page 67: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

67C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

level_db

• Stores arbitrary byte arrays• Data is stored sorted by key• Three operations: Put/Get/Delete• Multiple changes in atomic batch operations• Data is automatically compressed• Edis uses the Riak leveldb bindings

Page 68: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

69C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Part 2

Performance

Page 69: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

70C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Performance

• Major testing with redis-benchmark• Custom benchmark code• All testing with physical servers • Intel i5 760 quad-core @ 2.8 GHz• Erlang R14B04

Page 70: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

71C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Performance 1

It's important to remember that edis respects Redis's goals of algorithmic complexity.

If a Redis command is O(log(n)), Edis will have the same O().*

* Except for ZSETS - We don't yet have skiplists in Erlang

Page 71: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

72C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Performance 2(Operations/second)

PING (inline)PINGMSET (10 keys)SETGETINCRLPUSHLPOPSADDSPOPLRANGE (first 100 elements)

Redis In-Memory Edis % slower120,734 40,741 296%129,892 32,956 394%

73,825 6,662 1,108%135,160 22,051 613%134,282 23,127 581%138,916 24,421 569%137,990 21,397 645%130,769 22,728 575%135,160 21,860 618%132,456 25,707 515%

65,362 1,783 3,667%

Page 72: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

73C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Performance 3(Operations/second)

PING (inline)PINGMSET (10 keys)SETGETINCRLPUSHLPOPSADDSPOPLRANGE (first 100 elements)

Redis In-Memory Edis % slower120,734 40,741 296%129,892 32,956 394%

73,825 6,662 1,108%135,160 22,051 613%134,282 23,127 581%138,916 24,421 569%137,990 21,397 645%130,769 22,728 575%135,160 21,860 618%132,456 25,707 515%

65,362 1,783 3,667%

Page 73: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

74C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Performance 4(Operations/second)

PING (inline)PINGMSET (10 keys)SETGETINCRLPUSHLPOPSADDSPOPLRANGE (first 100 elements)

Redis LevelDB Edis % slower120,734 41,152 293%129,892 32,419 401%

73,825 6,058 1,219%135,160 20,726 652%134,282 21,463 626%138,916 17,930 775%137,990 226 61,105%130,769 229 57,092%135,160 9,003 1,501%132,456 1,298 10,205%

65,362 644 10,143%

Page 74: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

75C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Performance 5(Operations/second)

PING (inline)PINGMSET (10 keys)SETGETINCRLPUSHLPOPSADDSPOPLRANGE (first 100 elements)

Redis LevelDB Edis % slower120,734 41,152 293%129,892 32,419 401%

73,825 6,058 1,219%135,160 20,726 652%134,282 21,463 626%138,916 17,930 775%137,990 226 61,105%130,769 229 57,092%135,160 9,003 1,501%132,456 1,298 10,205%

65,362 644 10,143%

Page 75: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

76C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Part 3

Using (and Extending) Edis

Page 76: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

77C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Extending with Hooks

• Similar to Riak "post commit" hooks• In-process • Only operates on lists (sets/hashes TBD)• Set in Erlang config-file - no realtime creation• Not officially merged yet

Page 77: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

78C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Extending with Hooks 2

• Can implement the "Reliable Queue" pattern• Could interface with RabbitMQ • Could do "additional resource checks"

Page 78: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

79C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

What's next

• Performance Improvements • Support for Master/Slave • Roadmap for Multi-Master Replication• Custom command runners• RabbitMQ Hooks

• Riak backend support

Page 79: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

80C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

For additional fun...

• Look at the edis source • Lots of Benchmarks w/ common test • We're using: * -extends directive * Parameterized Modules * Custom behaviors * Ascii Art

Page 80: Edis: Implementing Redis in Erlang · Project Edis Author C B DePue III File Implementing Redis In Erlang.graffle Date Thu Mar 29 2012 2 2 Edis: Implementing Redis in Erlang A step-by-step

81C B DePue IIIAuthorProject Implementing Redis In Erlang.graffleFile Thu Mar 29 2012DateEdis

Thanks!

• github.com/inaka/edis• @chaddepue• [email protected]