Consensus State
\documentclass[border=2pt]{standalone} %% Fonts %\usepackage{fontspec} %% Default Features %\defaultfontfeatures{ % Mapping=tex-text, % Ligatures=TeX, %} %% Serif Font %\setmainfont[ % UprightFont=EBGaramond-Regular, % ItalicFont=EBGaramond-Italic, % BoldFont=EBGaramond-Bold, % BoldItalicFont=EBGaramond-BoldItalic, %]{EB Garamond} %% Mono Font %\setmonofont[ % UprightFont=JetBrainsMonoNL-Regular, % ItalicFont=JetBrainsMonoNL-Italic, % BoldFont=JetBrainsMonoNL-Bold, % BoldItalicFont=JetBrainsMonoNL-BoldItalic, %] %{JetBrains Mono} % Tikz \usepackage{tikz} \usetikzlibrary{calc, positioning, shapes} % Colors %\definecolor{myyellow}{RGB}{255, 255, 191} %\definecolor{mygreen}{RGB}{171, 221, 164} %\definecolor{myblue}{RGB}{216, 225, 246} % Dimensions \def\deltadim{0.1} \def\cornerradius{0.2cm} \def\innersep{6pt} \def\outersep{2pt} % Threads \def\threaddrawcolor{yellow!60!black} \def\threadfillcolor{yellow!20} \def\shift{1cm} %% Peer threads \def\numpeerthreads{4} %% Service Threads \def\numservicethreads{3} %% Timer Threads \def\numtimerthreads{2} % Consensus State \def\consensusstatedrawcolor{green!70!black} \def\consensusstatefillcolor{green!20} \def\consensusstateheight{2.25cm} \def\consensusstatewidth{4.5cm} % Lock \def\lockdrawcolor{orange!50!black} \def\lockfillcolor{orange!50} \def\lockhandlecolor{black} \def\locksize{12pt} % Data Store \def\datastoredrawcolor{orange!80!black} \def\datastorefillcolor{orange!60} \def\datastoreheight{6pt} \def\datastorewidth{12pt} % Styles \tikzset{ % labels label/.style={ font=\small\ttfamily, align=center, }, % node labels node_label/.style={ font=\small, align=center, }, % general module/.style={ draw, very thick, label, outer sep=\outersep, rounded corners=\cornerradius, shape=rectangle, }, % threads thread/.style={ module, draw=\threaddrawcolor, fill=\threadfillcolor, inner xsep=\innersep, inner ysep=\innersep, }, % consensus state consensus_state/.style={ module, draw=\consensusstatedrawcolor, fill=\consensusstatefillcolor, minimum height=\consensusstateheight, minimum width=\consensusstatewidth, }, % parts of consensus state consensus_state_parts/.style={ module, draw=\consensusstatedrawcolor, fill=\consensusstatefillcolor, inner xsep=\innersep, inner ysep=\innersep, }, % lock lock_body/.style={ draw=\lockdrawcolor, fill=\lockfillcolor, very thick, shape=rectangle, minimum size=\locksize, inner sep=0, outer sep=0, }, lock_handle/.style={ draw=black, very thick, looseness=2 }, % data store data_store/.style={ draw=\datastoredrawcolor, fill=\datastorefillcolor, thick, ellipse, inner sep=0, minimum height=\datastoreheight, minimum width=\datastorewidth, }, % connections connection/.style={ thick, -stealth, }, % traffic inbound_traffic/.style={ very thick, latex-, }, outbound_traffic/.style={ very thick, -latex, } } \begin{document} \begin{tikzpicture} % Consensus state \node [ consensus_state, ] (consensus state) {consensus state}; %% Configuration \node [ consensus_state_parts, anchor=south west, shift={(0,-\shift*2)}, ] (configuration) at (consensus state.south west) {configuration}; %% Lock \coordinate (lock_body_x) at ($(configuration.mid)!0.5!(configuration.west)$); \node[ lock_body, anchor=north, shift={(0,\outersep + \locksize/2)}, ] (lock_body) at (lock_body_x|-consensus state.south) {}; \draw[ lock_handle ] (lock_body.125) to[out=90, in=90] (lock_body.55); %% Log \node [ consensus_state_parts, anchor=south east, shift={(0,-\shift*2)}, ] (log) at (consensus state.south east) {log}; %% Data store \foreach \i in {0,...,2} { \node[ data_store, shift={(\datastorewidth/10,\i * \datastoreheight/2)}, ] at (log.south east) {}; } % Peer threads \coordinate (peer_thread) at ($(consensus state.south west) + (-\shift,0)$); \foreach \i in {1,...,\numpeerthreads} { \pgfmathsetmacro{\displacement}{\i * \deltadim} \node[ thread, anchor=east ] (peer_thread\i) at ($(peer_thread) + (-\displacement,\displacement)$) {peer\\thread}; } % Service threads \coordinate (service_thread) at ($(consensus state.north west) + (-\shift,0)$); \foreach \i in {1,...,\numservicethreads} { \pgfmathsetmacro{\displacement}{\i * \deltadim} \node[ thread, anchor=east ] (service_thread\i) at ($(service_thread) + (-\displacement,\displacement)$) {service\\thread}; } % State Machine \node[ thread, anchor=south ] (state_machine_thread) at ($(consensus state.north) + (0,\shift)$) {state machine\\thread}; % Timer threads \coordinate (timer_thread) at ($(consensus state.north east) + (\shift,0)$); \foreach \i in {1,...,\numtimerthreads} { \pgfmathsetmacro{\displacement}{\i * \deltadim} \node[ thread, anchor=west ] (timer_thread\i) at ($(timer_thread) + (-\displacement,\displacement)$) {timer\\thread}; } % Log synch thread \node[ thread, anchor=west ] (log_synch_thread) at ($(consensus state.south east) + (\shift,0)$) {log synch\\thread}; % Part of \draw[thick] (consensus state.south-|configuration) -- (configuration); \draw[thick] (consensus state.south-|log) -- (log); % Traffic \draw[ inbound_traffic, node_label ] (service_thread\numservicethreads) -- +(-\shift*3,0) node[pos=0.5, above, align=center] {inbound\\RPCs}; \draw[ outbound_traffic, node_label ] (peer_thread\numpeerthreads) -- +(-\shift*3,0) node[pos=0.5, above, align=center] {outbound\\RPCs}; % Connections \draw[connection] (log_synch_thread) -- (log); \draw[connection] (log_synch_thread) -- (consensus state); \draw[connection] (timer_thread\numtimerthreads) -- (consensus state); \draw[connection] (state_machine_thread) -- (consensus state); \draw[connection] (service_thread1) -- (consensus state); \draw[connection] (peer_thread1) -- (consensus state); \end{tikzpicture} \end{document}
Replicated State Machine
\documentclass[border=2pt]{standalone} %% Fonts %\usepackage{fontspec} %% Default Features %\defaultfontfeatures{ % Mapping=tex-text, % Ligatures=TeX, %} %% Serif Font %\setmainfont[ % UprightFont=EBGaramond-Regular, % ItalicFont=EBGaramond-Italic, % BoldFont=EBGaramond-Bold, % BoldItalicFont=EBGaramond-BoldItalic, %]{EB Garamond} %% Mono Font %\setmonofont[ % UprightFont=JetBrainsMonoNL-Regular, % ItalicFont=JetBrainsMonoNL-Italic, % BoldFont=JetBrainsMonoNL-Bold, % BoldItalicFont=JetBrainsMonoNL-BoldItalic, %] %{JetBrains Mono} % Tikz \usepackage{tikz} \usetikzlibrary{calc, positioning, shapes} % Colors %\definecolor{myyellow}{RGB}{255, 255, 191} %\definecolor{mygreen}{RGB}{171, 221, 164} %\definecolor{myblue}{RGB}{216, 225, 246} % Dimensions \def\deltadimclient{0.1} \def\deltadimserver{0.2} \def\padding{0.4cm} \def\cornerradius{0.2cm} \def\logentrieslinewidth{0.7pt} \def\innersep{6pt} \def\outersep{2pt} % Client \def\numclients{3} \def\clientdrawcolor{gray!60!black} \def\clientfillcolor{gray!25} % Server \def\numservers{4} \def\serverdrawcolor{\clientdrawcolor} \def\serverfillcolor{\clientfillcolor} \def\serverheight{5.7cm} \def\serverwidth{6.5cm} % Replicated \def\replicateddrawcolor{green!70!black} \def\replicatedfillcolor{green!20} % Entries \def\logentriesdrawcolor{cyan!100} \def\logentriesfillcolor{cyan!20} \def\entriesheight{15pt} \def\entrieswidth{34pt} \def\textspace{2mm} % Data Store \def\datastoredrawcolor{orange!80!black} \def\datastorefillcolor{orange!60} \def\datastoreheight{9pt} \def\datastorewidth{18pt} % Connections \def\connectionshift{0.35} \def\labelinnersep{1.5pt} % Styles \tikzset{ % labels label/.style={ font=\footnotesize\ttfamily, align=center, }, % node labels node_label/.style={ draw, thick, inner sep=\labelinnersep, shape=circle, align=center, }, % general module/.style={ draw, very thick, label, outer sep=\outersep, rounded corners=\cornerradius, shape=rectangle, }, % client client/.style={ module, draw=\clientdrawcolor, fill=\clientfillcolor, inner xsep=\innersep, inner ysep=\innersep, }, % server server/.style={ module, draw=\serverdrawcolor, fill=\serverfillcolor, minimum height=\serverheight, minimum width=\serverwidth, }, % replicated replicated/.style={ module, draw=\replicateddrawcolor, fill=\replicatedfillcolor, inner sep = \innersep, }, % log and state machine entries entries/.style={ shape=rectangle, draw=\logentriesdrawcolor, line width=\logentrieslinewidth, fill=\logentriesfillcolor, rounded corners=0cm, minimum height=\entriesheight, minimum width=\entrieswidth, inner ysep=0pt, inner xsep=\innersep/2, outer sep=0pt, }, % data store data_store/.style={ draw=\datastoredrawcolor, fill=\datastorefillcolor, thick, ellipse, inner sep=0, minimum height=\datastoreheight, minimum width=\datastorewidth, }, % connections connection/.style={ thick, -stealth, } } \begin{document} \begin{tikzpicture} % Server \foreach \i in {1,...,\numservers} { \pgfmathsetmacro{\displacement}{\i * \deltadimserver} \node[ server, anchor = west, ] (server\i) at (-\displacement, \displacement) {}; } %% Label \node[ label, anchor=north west, shift={(\padding,-\padding)}, ] at (server\numservers.north west){server}; % Log \node[ replicated, anchor = south west, shift={(\padding,\padding)}, ] (log) at (server\numservers.south west) {% log % \\[\textspace] % \begin{tikzpicture} \node[ entries ] (log1) {$x \leftarrow 3$}; % \node[ entries, anchor=west, xshift=-\logentrieslinewidth ] (log2) at (log1.east) {$y \leftarrow 7$}; % \node[ entries, anchor=west, xshift=-\logentrieslinewidth ] (log3) at (log2.east) {$y \leftarrow 9$}; % \node[ entries, anchor=west, xshift=-\logentrieslinewidth ] (log4) at (log3.east) {$\cdots$}; \end{tikzpicture}% }; %% Data store \foreach \i in {0,...,2} { \node[ data_store, shift={(\datastorewidth/6,\i * \datastoreheight/2)}, ] at (log.south east) {}; } % State Machine \node[ replicated, anchor = north east, shift={(-\padding,-\padding)}, ] (state machine) at (server\numservers.north east) {% state machine % \\[\textspace] % \begin{tikzpicture} \node[ entries ] (sm1) {$x : 3$}; % \node[ entries, anchor=north, yshift=\logentrieslinewidth ] (sm2) at (sm1.south) {$y : 9$}; % \node[ entries, anchor=north, yshift=\logentrieslinewidth ] (sm3) at (sm2.south) {$z : 0$}; % \end{tikzpicture} }; % Consensus Module \node[ replicated, anchor = west, shift={(\padding,0)}, ] (consensus module) at (server\numservers.west|-state machine.west) {consensus\\module}; % Client \coordinate (client) at (-3,0|-consensus module); \foreach \i in {1,...,\numclients} { \pgfmathsetmacro{\displacement}{\i * \deltadimclient} \node[ client, ] (client\i) at ($(client) + (-\displacement,\displacement)$) {client}; } % Arrows %% client -> consensus module \draw[connection] (client\numclients) to[out=50, in=150] node[node_label, shift={(0,-\connectionshift)}] {1} (consensus module); %% consensus module -> log \draw[connection] (consensus module) to[out=270, in=140] node[node_label, shift={(-\connectionshift,0)}] {2} (log); %% log -> state machine \draw[connection] (log) to[out=0, in=300] node[node_label, pos=0.7, shift={(\connectionshift,0)}] {3} (state machine); %% state machine -> client \draw[connection] (state machine) to[out=140, in=70] node[node_label, shift={(0,\connectionshift)}] {4} (client\numclients); %% consensus module -> server \foreach \i in {1,...,\numservers} { \ifnum\i=\numservers\else \draw[connection] (consensus module) to[out=190, in=195, looseness=1.5] node[shift={(-\connectionshift,0)}] (server_node\i) {} (server\i.south west); \fi } %%% Label \node[ node_label ] at (server_node1) {2}; \end{tikzpicture} \end{document}
Unoptimized Raft Pipeline
\documentclass[border=2pt]{standalone} %% Fonts %\usepackage{fontspec} %% Default Features %\defaultfontfeatures{ % Mapping=tex-text, % Ligatures=TeX, %} %% Serif Font %\setmainfont[ % UprightFont=EBGaramond-Regular, % ItalicFont=EBGaramond-Italic, % BoldFont=EBGaramond-Bold, % BoldItalicFont=EBGaramond-BoldItalic, %]{EB Garamond} %% Mono Font %\setmonofont[ % UprightFont=JetBrainsMonoNL-Regular, % ItalicFont=JetBrainsMonoNL-Italic, % BoldFont=JetBrainsMonoNL-Bold, % BoldItalicFont=JetBrainsMonoNL-BoldItalic, %] %{JetBrains Mono} % Tikz \usepackage{tikz} \usetikzlibrary{calc, positioning, shapes} % Colors %\definecolor{myyellow}{RGB}{255, 255, 191} %\definecolor{mygreen}{RGB}{171, 221, 164} %\definecolor{myblue}{RGB}{216, 225, 246} % Dimensions \def\deltadim{0.2pt} \def\innersep{3pt} \def\servershift{1.5cm} \def\shortenlen{2pt} % Pipeline stages \def\stageslinewidth{1.5pt} \def\stagesdrawcolor{magenta!100} \def\stagesfillcolor{magenta!20} \def\stagesheight{30pt} \def\stageswidth{66pt} %% Followers \def\followersnum{4} % Connections \def\connectionshift{0.35} \def\labelinnersep{1.5pt} % Styles \tikzset{ % labels label/.style={ font=\large\ttfamily, align=center, }, % Pipeline stages stages/.style={ shape=rectangle, draw=\stagesdrawcolor, line width=\stageslinewidth, fill=\stagesfillcolor, rounded corners=0cm, minimum height=\stagesheight, minimum width=\stageswidth, label, inner ysep=0pt, inner xsep=\innersep, outer sep=0pt, }, % connections connection/.style={ very thick, -stealth, shorten <=\shortenlen , shorten >=\shortenlen } } \begin{document} \begin{tikzpicture} % Leader replicates log \node[ stages ] (leader_receive) {receive}; % \node[ stages, anchor=west, ] (leader_append) at (leader_receive.east) {append}; % \node[ stages, anchor=west, ] (leader_sync) at (leader_append.east) {sync}; % Followers receive AppendEntries \foreach \i in {\followersnum,...,1} { \pgfmathsetmacro{\displacement}{(\i-1) * \deltadim} \node[ stages, anchor=west, shift={(\servershift,0)}, ] (follower_request\i) at ($(leader_sync.east) + (\displacement,-\displacement)$) {request}; % \node[ stages, anchor=west, ] (follower_append\i) at (follower_request\i.east) {append}; % \node[ stages, anchor=west, ] (follower_sync\i) at (follower_append\i.east) {sync}; % \node[ stages, anchor=west, ] (follower_response\i) at (follower_sync\i.east) {response}; } % Leader applies committed entries \node[ stages, anchor=west, shift={(\servershift,0)}, ] (leader_commit) at (follower_response1.east-|follower_response\followersnum.east) {commit}; % \node[ stages, anchor=west, ] (leader_apply) at (leader_commit.east) {apply}; % \node[ stages, anchor=west, ] (leader_reply) at (leader_apply.east) {reply}; % Connections %% Leader -> Followers \foreach \i in {\followersnum,...,1} { \draw [ connection ] (leader_sync.east) to[out=0, in=210] (follower_request\i.south west); } %% Followers -> Leader \foreach \i in {\followersnum,...,1} { \draw [ connection ] (follower_response\i.north east) to[out=30, in=180] (leader_commit.west); } % Labels \pgfmathsetmacro{\consensus}{int(\followersnum/2)} \node [ align=center, shift={(0,1.5)} ] at ($(follower_response1)!0.5!(leader_commit)$) {\Large wait for \\\Large\consensus\ out of \followersnum}; \end{tikzpicture} \end{document}
Optimized Raft Pipeline
\documentclass[border=2pt]{standalone} %% Fonts %\usepackage{fontspec} %% Default Features %\defaultfontfeatures{ % Mapping=tex-text, % Ligatures=TeX, %} %% Serif Font %\setmainfont[ % UprightFont=EBGaramond-Regular, % ItalicFont=EBGaramond-Italic, % BoldFont=EBGaramond-Bold, % BoldItalicFont=EBGaramond-BoldItalic, %]{EB Garamond} %% Mono Font %\setmonofont[ % UprightFont=JetBrainsMonoNL-Regular, % ItalicFont=JetBrainsMonoNL-Italic, % BoldFont=JetBrainsMonoNL-Bold, % BoldItalicFont=JetBrainsMonoNL-BoldItalic, %] %{JetBrains Mono} % Tikz \usepackage{tikz} \usetikzlibrary{calc, positioning, shapes} % Colors %\definecolor{myyellow}{RGB}{255, 255, 191} %\definecolor{mygreen}{RGB}{171, 221, 164} %\definecolor{myblue}{RGB}{216, 225, 246} % Dimensions \def\deltadim{0.2pt} \def\innersep{3pt} \def\servershift{1.5cm} \def\shortenlen{2pt} % Pipeline stages \def\stageslinewidth{1.5pt} \def\stagesdrawcolor{magenta!100} \def\stagesfillcolor{magenta!20} \def\stagesheight{30pt} \def\stageswidth{66pt} %% Followers \def\followersnum{4} % Connections \def\connectionshift{0.35} \def\labelinnersep{1.5pt} % Styles \tikzset{ % labels label/.style={ font=\large\ttfamily, align=center, }, % Pipeline stages stages/.style={ shape=rectangle, draw=\stagesdrawcolor, line width=\stageslinewidth, fill=\stagesfillcolor, rounded corners=0cm, minimum height=\stagesheight, minimum width=\stageswidth, label, inner ysep=0pt, inner xsep=\innersep, outer sep=0pt, }, % connections connection/.style={ very thick, -stealth, shorten <=\shortenlen , shorten >=\shortenlen } } \begin{document} \begin{tikzpicture} % Leader replicates log \node[ stages ] (leader_receive) {receive}; % \node[ stages, anchor=west, ] (leader_append) at (leader_receive.east) {append}; % \node[ stages, anchor=west, ] (leader_sync) at (leader_append.east) {sync}; % Followers receive AppendEntries \foreach \i in {\followersnum,...,1} { \pgfmathsetmacro{\displacement}{(\i-1) * \deltadim} \node[ stages, anchor=west, shift={(\servershift,0)}, ] (follower_request\i) at ($(leader_sync.east) + (\displacement,-\displacement)$) {request}; % \node[ stages, anchor=west, ] (follower_append\i) at (follower_request\i.east) {append}; % \node[ stages, anchor=west, ] (follower_sync\i) at (follower_append\i.east) {sync}; % \node[ stages, anchor=west, ] (follower_response\i) at (follower_sync\i.east) {response}; } % Leader applies committed entries \node[ stages, anchor=west, shift={(\servershift,0)}, ] (leader_commit) at (follower_response1.east-|follower_response\followersnum.east) {commit}; % \node[ stages, anchor=west, ] (leader_apply) at (leader_commit.east) {apply}; % \node[ stages, anchor=west, ] (leader_reply) at (leader_apply.east) {reply}; % Connections %% Leader -> Followers \foreach \i in {\followersnum,...,1} { \draw [ connection ] (leader_sync.east) to[out=0, in=210] (follower_request\i.south west); } %% Followers -> Leader \foreach \i in {\followersnum,...,1} { \draw [ connection ] (follower_response\i.north east) to[out=30, in=180] (leader_commit.west); } % Labels \pgfmathsetmacro{\consensus}{int(\followersnum/2)} \node [ align=center, shift={(0,1.5)} ] at ($(follower_response1)!0.5!(leader_commit)$) {\Large wait for \\\Large\consensus\ out of \followersnum}; \end{tikzpicture} \end{document}