• Stars
    star
    650
  • Rank 69,218 (Top 2 %)
  • Language
    Ruby
  • License
    MIT License
  • Created almost 13 years ago
  • Updated almost 9 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Convergent Replicated Data Types

Meangirls

Serializable data types for eventually consistent systems.

Installation

Install locally:

$ bundle install
$ rake build
$ gem install pkg/meangirls-0.1.0.gem

Or, you can reference it from your Gemfile:

gem "meangirls", github: "aphyr/meangirls", branch: "master"

Data Types

Sets

G-Set

Set union is commutative and convergent; hence it is always safe to have simultaneous writes to a set which only allows addition. You cannot remove an element of a G-Set.

JSON:

{
  'type': 'g-set',
  'e': ['a', 'b', 'c']
}

2P-Set

2-phase sets consist of two g-sets: one for adding, and another for removing. To add an element, add it to the add set A. To remove e, add e to the remove set R. An element can only be added once, and only removed once. Elements can only be removed if they are present in the set. Removes take precedence over adds.

JSON:

{
  'type': '2p-set',
  'a': ['a', 'b'],
  'r': ['b']
}

In this set, only 'a' is present.

LWW-Element-Set

LWW-Element-Set is like 2P-Set: it comprises an add G-Set (A) and a remove G-Set (R), with a timestamp for each element. To add an element e, add (e, timestamp) to the add set A. To remove e, add (e, timestamp) to the remove set R. An element is present iff it is in A, and no newer element exists in R. Merging is accomplished by taking the union of all A and all R, respectively.

Since the last write wins, we can safely take only the largest add, and the largest delete. All others can be pruned.

When A and R have equal timestamps, the direction of the inequality determines whether adds or removes win. {'bias': 'a'} indicates that adds win. {'bias': 'r'} indicates that removes win. The default bias is 'a'.

Timestamps may be any ordered primitive: integers, floats, strings, etc. If a coordinated unique timestamp service is used, LWW-Element-Set behaves like a traditional consistent Set structure. If non-unique timestamps are used, the resolution of the timestamp determines the window under which conflicts will be resolved by the bias towards adds or deletes.

TODO: define sorting strategies for strings. By byte value, UTF-8 ordering, numeric, etc...

In JSON, we write the set as a list of 2- or 3-tuples: [element, add-time] or [element, add-time, delete-time]

JSON:

{
  'type': 'lww-e-set',
  'bias': 'a',
  'e': [
    ['a', 0],
    ['b', 1, 2],
    ['c', 2, 1],
    ['d', 3, 3]
  ]
}

In this set:

  • a was created at 0 and still exists.
  • b was deleted after creation; it does not exist.
  • c was created after deletion; it exists
  • d was created and deleted at the same time. Bias a means we prefer adds, so it exists.

OR-Set

Observed-Removed Sets support adding and removing elements in a causally consistent manner. It resembles LWW-Set, except that instead of times, unique tags are associated with each insertion or deletion. In the case of conflicting add and delete, add wins. An element is a member of the set iff the set of insertion tags less the set of deletion tags is nonempty.

We write the set as a list of 2- or 3- tuples: [element, [add-tags]] or [element, [add-tags], [remove-tags]]

To insert e, generate a unique tag, and add it to the insertion tag set for e.

To remove e, take all insertion tags for e, and insert them into the deletion tags for e.

To merge two OR-Sets, for each element in either set, take the union of the insertion tags and the union of the deletion tags.

Tags may be any primitive: strings, ints, floats, etc.

JSON:

{
  'type': 'or-set',
  'e': [
    ['a', [1]],
    ['b', [1], [1]],
    ['c', [1, 2], [2, 3]]
  ]
}
  • a exists.
  • b's only insertion was deleted, so it does not exist.
  • c has two insertions, only one of which was deleted. It exists.

Max-Change-Sets

MC-Sets resolve divergent histories for an element by choosing the value which has changed the most. You cannot delete an element which is not present, and cannot add an element which is already present. MC-sets are compact and do the right thing when changes to elements are infrequent compared to the conflict resolution window, but behave arbitrarily when divergent histories each include many changes.

Each element e is associated with an integer n, implicitly assumed to be zero. When n is even, the element is absent from the set. When n is odd, the element is present. To add an element to the set, increment n from an even value by one; to remove an element, increment n from an odd value by one. To merge sets, take each element and choose the maximum value of n from each history.

When n is limited to [0, 2], Max-Change-Sets collapse to 2P-Sets. Unlike 2P-Sets, however, one can add and remove an arbitrary number of times. The disadvantage is that there is no bias towards preserving adds or removes. Instead, whichever history has incremented further (undergone more changes) is preferred.

In JSON, max-change sets are represented as a list of [element, n] tuples.

JSON:

{
  'type': 'mc-set',
  'e': [
    ['a', 1],
    ['b', 2],
    ['c', 3]
  ]
}
  • a is present
  • b is absent
  • c is present

Counters

G-Counter

A G-Counter is a grow-only counter (inspired by vector clocks) in which only increment and merge are possible. Incrementing the counter adds 1 to the count for the current actor. Divergent histories are resolved by taking the maximum count for each actor (like a vector clock merge). The value of the counter is the sum of all actor counts.

JSON:

{
  'type': 'g-counter',
  'e': {
    'a': 1,
    'b': 5,
    'c': 2
  }
}
  • The counter value is 8.

PN-Counter

PN-Counters allow the counter to be decreased by tracking the increments (P) separate from the decrements (N), both represented as internal G-Counters. Merge is handled by merging the internal P and N counters. The value of the counter is the value of the P counter minus the value of the N counter.

JSON:

{
  'type': 'pn-counter',
  'p': {
    'a': 10,
    'b': 2
  },
  'n': {
    'c': 5,
    'a': 1
  }
}
  • P=12, N=6, so the value is 6.

More Repositories

1

distsys-class

Class materials for a distributed systems lecture series
8,983
star
2

tesser

Clojure reducers, but for parallel execution: locally and on distributed systems.
Clojure
867
star
3

tund

SSH reverse tunnel daemon
Ruby
418
star
4

tea-time

Lightweight Clojure task scheduler
Clojure
240
star
5

salticid

A deployment system, with design goals 1: Magic and 2: More Magic
Ruby
222
star
6

dom-top

Unorthodox control flow, for Clojurists with masochistic sensibilities.
Clojure
204
star
7

timelike

A library for simulating parallel systems, in Clojure
Clojure
184
star
8

partitions-post

A blog post on network partitions in practice
182
star
9

clj-antlr

Clojure bindings for the ANTLR 4 parser
Clojure
167
star
10

less-awful-ssl

Sssh no tears, only TLS now. For Clojure.
Clojure
154
star
11

interval-metrics

Clojure data structures for performance metrics over discrete time intervals.
Clojure
118
star
12

dist-sagas

A paper on sagas in distributed systems
TeX
91
star
13

gretchen

Offline serializability verification, in Clojure
Clojure
68
star
14

prism

Automatically re-run clojure tests
Clojure
59
star
15

verschlimmbesserung

An etcd client with modern Clojure sensibilities
Clojure
56
star
16

merkle

Clojure Merkle Trees
Clojure
51
star
17

gnuplot

Clojure gnuplot bindings
Clojure
47
star
18

risky

A lightweight Ruby ORM for Riak
Ruby
40
star
19

schadenfreude

Clojure benchmarking tools
Clojure
35
star
20

jepsen-talks

Slides and resources for talks on partition tolerance
Clojure
33
star
21

meitner

Explodes Clojure functions and macros into dependency graphs
Clojure
30
star
22

aesahaettr

Sharding, partitioning, and consistent hashing for Clojure. May release spectres.
Clojure
26
star
23

bitcask-ruby

An (incomplete) interface to the Bitcask storage system
Ruby
19
star
24

ustate

micro state daemon
Ruby
18
star
25

salesfear

A Clojure salesforce client.
Clojure
17
star
26

construct

Extensible, persistent, structured configuration for Ruby
Ruby
16
star
27

skewbinheap

A Skew Binomial Heap for Erlang.
Erlang
15
star
28

yamr

A Linux Yammer client.
Ruby
12
star
29

bifurcan-clj

Clojure wrapper for the Bifurcan family of data structures
Clojure
12
star
30

tumblr-archiver

Hacky Clojure program to download media from tumblr liked posts
Clojure
12
star
31

cyclic.js

Cyclic time series data structures for javascript
JavaScript
10
star
32

riemann-bench

An example for using the Reimann Clojure client
Clojure
10
star
33

london-gen

Silly London Landmarks
Clojure
8
star
34

gifdex

A gif tagging server for local use
Clojure
8
star
35

mtrc

Ruby metrics
Ruby
8
star
36

adaptive-executor

Adaptive threadpool executor experiment
Clojure
6
star
37

lights

Change your Hue lights to randomly generated colors, continuously
Clojure
5
star
38

thought-leaders

The definitive list of thought leaders
5
star
39

mastodon-utils

Utilities for working with Mastodon's API
Clojure
5
star
40

prometheus-mastodon-exporter

Exports Mastodon statistics for polling by Prometheus
Clojure
5
star
41

cortex-reaver

A dangerous Ruby blog engine, with a photographic memory.
Ruby
5
star
42

hangman

A ridiculously overpowered hangman AI in Clojure
Clojure
4
star
43

qsd-phase-space-reconstruction

Some ruby scripts for exploring datasets in an attempt to reconstruct phase space dynamics (and to identify lyapunov exponents) of a QSD-simulated Duffing oscillator
Ruby
4
star
44

exocora

A lightweight CGI script framework
Ruby
3
star
45

joedahato

Predict's Joe Damato's hat choices
Clojure
3
star
46

tattoo

Overkill
Clojure
2
star
47

producer_consumer

Ruby queue-backed producer consumer gem
Ruby
2
star
48

ruby-vodpod

Ruby bindings for the Vodpod API.
Ruby
2
star
49

frisk-management

NLP + erotic fiction -> PowerPoint slides
Clojure
2
star
50

heliotrope

A client for the distributed processing system Fabric
Ruby
2
star
51

qsd-tangent

Fork of QSD library with tangent space evolution
C++
2
star
52

caremad

Consistent Commutative Replicated DataTypes
2
star
53

euler-clj

Project Euler solutions in Clojure
Clojure
1
star
54

req-replay

silly experiment
Clojure
1
star
55

autotags

Jquery javascript tag editor with autocomplete
JavaScript
1
star
56

riakeys

Riak key cache (apparently impossible)
Clojure
1
star
57

clojure-perf

Mucking around with clojure performance testing
Clojure
1
star
58

mecha-query

Clojure
1
star