| an eventually consistent store can run demanding production applications | the paper's claimed contribution | [1] §1
It demonstrates that an eventually-consistent storage system can be used in production with demanding applications. |
| always readable and writable | the shopping cart requirement | [1] §1
customers should be able to view and add items to their shopping cart even if disks are failing, network routes are flapping, or data centers are being destroyed by tornados. |
| consistent hashing, object versioning, quorum-like, replica synchronisation, gossip | the techniques combined | [1] §1
Data is partitioned and replicated using consistent hashing [10], and consistency is facilitated by object versioning [12]. |
| the first N healthy nodes | whom operations contact | [1] §4.5
Read and write operations involve the first N healthy nodes in the preference list, skipping over those that are down or inaccessible. |
| tens of millions of customers, tens of thousands of servers | platform scale | [1] §1
Amazon runs a world-wide e-commerce platform that serves tens of millions customers at peak times using tens of thousands of servers located in many data centers around the world. |
| the standard mode of operation | failure | [1] §1
Dealing with failures in an infrastructure comprised of millions of components is our standard mode of operation |
| well over 3 million | shopping cart checkouts in a day | [1] §1
served tens of millions requests that resulted in well over 3 million checkouts in a single day |
| get and put by key, no multi-item operations | the query model | [1] §2.1
No operations span multiple data items and there is no need for relational schema. |
| usually under 1 MB | object size | [1] §2.1
Dynamo targets applications that need to store objects that are relatively small (usually less than 1 MB). |
| none; single-key updates only | isolation | [1] §2.1
Dynamo does not provide any isolation guarantees and permits only single key updates. |
| none; the environment is assumed non-hostile | security | [1] §2.1
Its operation environment is assumed to be non-hostile and there are no security related requirements such as authentication and authorization. |
| up to hundreds of storage hosts | design scale | [1] §2.1
its initial design targets a scale of up to hundreds of storage hosts. |
| over 150 | services behind one page | [1] §2.2
a page request to one of the e-commerce sites typically requires the rendering engine to construct its response by sending requests to over 150 services. |
| 300 ms for 99.9% of requests at 500 requests per second | an example service level agreement | [1] §2.2
provide a response within 300ms for 99.9% of its requests for a peak client load of 500 requests per second. |
| the 99.9th percentile | where SLAs are measured | [1] §2.2
at Amazon, SLAs are expressed and measured at the 99.9th percentile of the distribution. |
| an "always writeable" data store | the design space | [1] §2.3
Dynamo targets the design space of an “always writeable” data store |
| at read time | where conflict resolution happens | [1] §2.3
This requirement forces us to push the complexity of conflict resolution to the reads in order to ensure that writes are never rejected. |
| the application, or last write wins | who resolves conflicts | [1] §2.3
the application that maintains customer shopping carts can choose to “merge” the conflicting versions and return a single unified shopping cart. |
| eventual consistency | the consistency model | [1] §2.3
Dynamo is designed to be an eventually consistent data store; that is all updates reach all replicas eventually. |
| application-level conflict resolution | Bayou | [1] §3.2
Bayou allows application level resolution. |
| limited in scalability and availability | strongly consistent replication | [1] §3.2
these systems are limited in scalability and availability [7]. |
| incremental scalability | principle 1 | [1] §2.3
Incremental scalability: Dynamo should be able to scale out one storage host (henceforth, referred to as “node”) at a time, with minimal impact on both operators of the system and the system itself. |
| symmetry | principle 2 | [1] §2.3
Symmetry: Every node in Dynamo should have the same set of responsibilities as its peers; there should be no distinguished node or nodes that take special roles or extra set of responsibilities. |
| decentralization | principle 3 | [1] §2.3
Decentralization: An extension of symmetry, the design should favor decentralized peer-to-peer techniques over centralized control. |
| heterogeneity | principle 4 | [1] §2.3
Heterogeneity: The system needs to be able to exploit heterogeneity in the infrastructure it runs on. |
| MD5, 128 bits | the hash | [1] §4.1
It applies a MD5 hash on the key to generate a 128-bit identifier, which is used to determine the storage nodes that are responsible for serving the key. |
| the hash output range as a circle | the ring | [1] §4.2
the output range of a hash function is treated as a fixed circular space or “ring” |
| a random position on the ring | a node's place | [1] §4.2
Each node in the system is assigned a random value within this space which represents its “position” on the ring. |
| the first node clockwise | a key's node | [1] §4.2
Each data item identified by a key is assigned to a node by hashing the data item’s key to yield its position on the ring, and then walking the ring clockwise to find the first node with a position larger than the item’s position. |
| only the immediate neighbours | what a join affects | [1] §4.2
departure or arrival of a node only affects its immediate neighbors and other nodes remain unaffected. |
| stores three ranges | Figure 2's node D | [1] §4.3
Node D will store the keys that fall in the ranges (A, B], (B, C], and (C, D]. |
| non-uniform load; ignores heterogeneity | problems with one point per node | [1] §4.2
the random position assignment of each node on the ring leads to non-uniform data and load distribution. |
| several points per node | virtual nodes | [1] §4.2
instead of mapping a node to a single point in the circle, each node gets assigned to multiple points in the ring. |
| the positions a node is given | tokens | [1] §4.2
when a new node is added to the system, it is assigned multiple positions (henceforth, “tokens”) in the ring. |
| a failed node's load is dispersed | virtual node advantage 1 | [1] §4.2
If a node becomes unavailable (due to failures or routine maintenance), the load handled by this node is evenly dispersed across the remaining available nodes. |
| N, set per instance | replication factor | [1] §4.3
Each data item is replicated at N hosts, where N is a parameter configured “per-instance”. |
| the N-1 clockwise successors | where replicas go | [1] §4.3
the coordinator replicates these keys at the N-1 clockwise successor nodes in the ring. |
| the nodes responsible for a key | the preference list | [1] §4.3
The list of nodes that is responsible for storing a particular key is called the preference list. |
| more than N | its length | [1] §4.3
To account for node failures, preference list contains more than N nodes. |
| skip positions so nodes are distinct | its construction | [1] §4.3
the preference list for a key is constructed by skipping positions in the ring to ensure that the list contains only distinct physical nodes. |
| T random tokens per node, partition by token value | Strategy 1 | [1] §6.2
Strategy 1: T random tokens per node and partition by token value: This was the initial strategy deployed in production |
| slow bootstrapping, Merkle recomputation, no easy snapshot | what went wrong | [1] §6.2
during busy shopping season, when the nodes are handling millions of requests a day, the bootstrapping has taken almost a day to complete. |
| T random tokens per node, equal-sized partitions | Strategy 2 | [1] §6.2
Strategy 2: T random tokens per node and equal sized partitions: In this strategy, the hash space is divided into Q equally sized partitions/ranges and each node is assigned T random tokens. |
| Q/S tokens per node, equal-sized partitions | Strategy 3 | [1] §6.2
Strategy 3: Q/S tokens per node, equal-sized partitions: Similar to strategy 2, this strategy divides the hash space into Q equally sized partitions and the placement of partition is decoupled from the partitioning scheme. |
| much larger than N and S*T | Q | [1] §6.2
Q is usually set such that Q >> N and Q >> S*T, where S is the number of nodes in the system. |
| mean load over the hottest node's load | load-balancing efficiency | [1] §6.2
Load balancing efficiency is defined as the ratio of average number of requests served by each node to the maximum number of requests served by the hottest node. |
| S = 30, N = 3 | the experiment | [1] §6.2
The efficiency of these three strategies is evaluated for a system with S=30 and N=3. |
| Strategy 3 best, Strategy 2 worst | the ranking | [1] §6.2
strategy 3 achieves the best load balancing efficiency and strategy 2 has the worst load balancing efficiency. |
| three orders of magnitude less membership data | Strategy 3 against 1 | [1] §6.2
Strategy 3 achieves better efficiency and reduces the size of membership information maintained at each node by three orders of magnitude. |
| coordination on membership change | the price of Strategy 3 | [1] §6.2
The disadvantage of strategy 3 is that changing the node membership requires coordination in order to preserve the properties required of the assignment. |
| get() and put() | the interface | [1] §4.1
it exposes two operations: get() and put(). |
| one object, or a list of conflicting versions, with a context | what get returns | [1] §4.1
The get(key) operation locates the object replicas associated with the key in the storage system and returns a single object or a list of objects with conflicting versions along with a context. |
| the key, a context and the object | what put takes | [1] §4.1
The put(key, context, object) operation determines where the replicas of the object should be placed based on the associated key, and writes the replicas to disk. |
| opaque to the caller; carries the version | the context | [1] §4.1
The context encodes system metadata about the object that is opaque to the caller and includes information such as the version of the object. |
| any storage node | who accepts requests | [1] §4.5
Any storage node in Dynamo is eligible to receive client get and put operations for any key. |
| a load balancer, or a partition-aware client | routing a request | [1] §4.5
(1) route its request through a generic load balancer that will select a node based on load information, or (2) use a partition-aware client library that routes requests directly to the appropriate coordinator nodes. |
| typically the first of the top N | the coordinator | [1] §4.5
A node handling a read or write operation is known as the coordinator. Typically, this is the first among the top N nodes in the preference list. |
| forwarded to the first of the top N | a request at a non-replica | [1] §4.5
that node will forward the request to the first among the top N nodes in the preference list. |
| the minimum number of nodes for a read | R | [1] §4.5
R is the minimum number of nodes that must participate in a successful read operation. |
| the minimum number of nodes for a write | W | [1] §4.5
W is the minimum number of nodes that must participate in a successful write operation. |
| R + W > N | the quorum rule | [1] §4.5
Setting R and W such that R + W > N yields a quorum-like system. |
| the slowest of R (or W) replicas | latency of an operation | [1] §4.5
the latency of a get (or put) operation is dictated by the slowest of the R (or W) replicas. |
| any node | who coordinates a read (§6.4) | [1] §6.4
Any Dynamo node can act as a coordinator for a read request. |
| a node of the preference list | who coordinates a write (§6.4) | [1] §6.4
Write requests on the other hand will be coordinated by a node in the key’s current preference list. |
| zero-hop: every node can route directly | routing | [1] §3.3
Dynamo can be characterized as a zero-hop DHT, where each node maintains enough routing information locally to route a request to the appropriate node directly. |
| multi-hop routing raises tail latency | why not Chord or Pastry | [1] §3.3
multi-hop routing increases variability in response times, thereby increasing the latency at higher percentiles. |
| stamp, write locally, send to N, W-1 replies | a put | [1] §4.5
Upon receiving a put() request for a key, the coordinator generates the vector clock for the new version and writes the new version locally. The coordinator then sends the new version (along with the new vector clock) to the N highest-ranked reachable nodes. If at least W-1 nodes respond then the write is considered successful. |
| accepted if any one node has written it | W = 1 | [1] §4.6
Applications that need the highest level of availability can set W to 1, which ensures that a write is accepted as long as a single node in the system has durably written the key it to its local store. |
| risk of inconsistency and a durability window | low W and R | [1] §6
low values of W and R can increase the risk of inconsistency as write requests are deemed successful and returned to the clients even if they are not processed by a majority of the replicas. |
| a higher W | what production uses | [1] §4.6
in practice, most Amazon services in production set a higher W to meet the desired level of durability. |
| a new, immutable version | a modification | [1] §4.4
Dynamo treats the result of each modification as a new and immutable version of the data. |
| ask the N, wait for R | a get | [1] §4.5
for a get() request, the coordinator requests all existing versions of data for that key from the N highest-ranked reachable nodes in the preference list for that key, and then waits for R responses before returning the result to the client. |
| all causally unrelated versions | what a get returns | [1] §4.5
If the coordinator ends up gathering multiple versions of the data, it returns all the versions it deems to be causally unrelated. |
| repair stale replicas opportunistically | read repair | [1] §5
This process is called read repair because it repairs replicas that have missed a recent update at an opportunistic time and relieves the anti-entropy protocol from having to do it. |
| a list of (node, counter) pairs | a vector clock | [1] §4.4
A vector clock is effectively a list of (node, counter) pairs. |
| counters less than or equal | the ancestor test | [1] §4.4
If the counters on the first object’s clock are less-than-or-equal to all of the nodes in the second clock, then the first is an ancestor of the second and can be forgotten. |
| the client passes the context from a read | updating | [1] §4.4
when a client wishes to update an object, it must specify which version it is updating. This is done by passing the context it obtained from an earlier read operation |
| [(Sx, 1)] | D1's clock | [1] §4.4
The system now has the object D1 and its associated clock [(Sx, 1)]. |
| [(Sx, 2)] | D2's clock | [1] §4.4
The system now also has object D2 and its associated clock [(Sx, 2)]. |
| [(Sx, 2), (Sy, 1)] | D3's clock | [1] §4.4
The system now has data D3 and its associated clock [(Sx, 2), (Sy, 1)]. |
| [(Sx, 2), (Sz, 1)] | D4's clock | [1] §4.4
The system now has D4 (descendant of D2) whose version clock is [(Sx, 2), (Sz, 1)]. |
| [(Sx, 2), (Sy, 1), (Sz, 1)] | the read context before D5 | [1] §4.4
The read's context is a summary of the clocks of D3 and D4, namely [(Sx, 2), (Sy, 1), (Sz, 1)]. |
| [(Sx, 3), (Sy, 1), (Sz, 1)] | D5's clock | [1] §4.4
The new data D5 will have the following clock: [(Sx, 3), (Sy, 1), (Sz, 1)]. |
| at a threshold of, say, 10 pairs the oldest is dropped | clock truncation | [1] §4.4
When the number of (node, counter) pairs in the vector clock reaches a threshold (say 10), the oldest pair is removed from the clock. |
| "has not surfaced" | truncation in production | [1] §4.4
this problem has not surfaced in production and therefore this issue has not been thoroughly investigated. |
| the system picks the descendant | syntactic reconciliation | [1] §4.4
Most of the time, new versions subsume the previous version(s), and the system itself can determine the authoritative version (syntactic reconciliation). |
| the client merges branches | semantic reconciliation | [1] §4.4
the client must perform the reconciliation in order to collapse multiple branches of data evolution back into one (semantic reconciliation). |
| "an add to cart operation is never lost" | the cart guarantee | [1] §4.4
Using this reconciliation mechanism, an “add to cart” operation is never lost. However, deleted items can resurface. |
| sloppy | the quorum | [1] §4.6
it does not enforce strict quorum membership and instead it uses a “sloppy quorum”; all read and write operations are performed on the first N healthy nodes from the preference list, which may not always be the first N nodes encountered while walking the consistent hashing ring. |
| purely local | failure detection | [1] §4.8.3
node A may consider node B failed if node B does not respond to node A’s messages (even if B is responsive to node C's messages). |
| A periodically retries B | after a failure | [1] §4.8.3
A periodically retries B to check for the latter's recovery. |
| carries the intended recipient | a hinted replica | [1] §4.6
The replica sent to D will have a hint in its metadata that suggests which node was the intended recipient of the replica (in this case A). |
| a separate local database, scanned periodically | where hints live | [1] §4.6
Nodes that receive hinted replicas will keep them in a separate local database that is scanned periodically. |
| the preference list spans several | data centres | [1] §4.6
the preference list of a key is constructed such that the storage nodes are spread across multiple data centers. |
| on recovery; then delete | delivery | [1] §4.6
Upon detecting that A has recovered, D will attempt to deliver the replica to A. Once the transfer succeeds, D may delete the object from its local store without decreasing the total number of replicas in the system. |
| hinted replicas may vanish first | when hints fail | [1] §4.7
Hinted handoff works best if the system membership churn is low and node failures are transient. |
| anti-entropy | permanent failures | [1] §4.7
Dynamo implements an anti-entropy (replica synchronization) protocol to keep the replicas synchronized. |
| leaves hash keys; parents hash children | a Merkle tree | [1] §4.7
A Merkle tree is a hash tree where leaves are hashes of the values of individual keys. Parent nodes higher in the tree are hashes of their respective children. |
| nothing to synchronise | equal roots | [1] §4.7
if the hash values of the root of two trees are equal, then the values of the leaf nodes in the tree are equal and the nodes require no synchronization. |
| per virtual node | one tree per key range | [1] §4.7
Each node maintains a separate Merkle tree for each key range (the set of keys covered by a virtual node) it hosts. |
| trees are recomputed on membership change | the drawback | [1] §4.7
The disadvantage with this scheme is that many key ranges change when a node joins or leaves the system thereby requiring the tree(s) to be recalculated. |
| an explicit administrator action | joining and leaving | [1] §4.8.1
it was deemed appropriate to use an explicit mechanism to initiate the addition and removal of nodes from a Dynamo ring. |
| a random peer every second | membership gossip | [1] §4.8.1
Each node contacts a peer chosen at random every second and the two nodes efficiently reconcile their persisted membership change histories. |
| nodes known to all | seeds | [1] §4.8.2
Seeds are nodes that are discovered via an external mechanism and are known to all nodes. |
| dropped | a global view of failures | [1] §4.8.3
Later it was determined that the explicit node join and leave methods obviates the need for a global view of failure state. |
| random tokens | a new node | [1] §4.9
When a new node (say X) is added into the system, it gets assigned a number of tokens that are randomly scattered on the ring. |
| takes (F, G], (G, A] and (A, X] | X between A and B | [1] §4.9
When X is added to the system, it is in charge of storing keys in the ranges (F, G], (G, A] and (A, X]. |
| the old holders offer, X confirms | a join's transfers | [1] §4.9
Therefore, nodes B, C, and D will offer to and upon confirmation from X transfer the appropriate set of keys. |
| full membership works for a couple of hundred nodes | the limit | [1] §6.6
This model works well for a system that contains couple of hundreds of nodes. |
| coordination, membership and failure detection, persistence | a node's software | [1] §5
each storage node has three main software components: request coordination, membership and failure detection, and a local persistence engine. |
| Java | language | [1] §5
All these components are implemented in Java. |
| event-driven, staged like SEDA | the substrate | [1] §5
The request coordination component is built on top of an event-driven messaging substrate where the message processing pipeline is split into multiple stages similar to the SEDA architecture [24]. |
| one per client request | state machines | [1] §5
Each client request results in the creation of a state machine on the node that received the client request. |
| five states | the read state machine | [1] §5
(i) send read requests to the nodes, (ii) wait for minimum number of required responses, (iii) if too few replies were received within a given time bound, fail the request, (iv) otherwise gather all the data versions and determine the ones to be returned and (v) if versioning is enabled, perform syntactic reconciliation and generate an opaque write context that contains the vector clock that subsumes all the remaining versions. |
| the node that replied fastest to the previous read | who coordinates a write | [1] §5
the coordinator for a write is chosen to be the node that replied fastest to the previous read operation which is stored in the context information of the request. |
| read-your-writes, and a better tail | why | [1] §5
This optimization enables us to pick the node that has the data that was read by the preceding read operation thereby increasing the chances of getting “read-your-writes” consistency. |
| admission control by slices | background tasks | [1] §6.5
Each of the background tasks uses this controller to reserve runtime slices of the resource (e.g. database), shared across all background tasks. |
| BDB Transactional Data Store | storage engines (1) | [1] §5
Engines that are in use are Berkeley Database (BDB) Transactional Data Store |
| BDB Java Edition, MySQL, in-memory buffer | storage engines (2) | [1] §5
BDB Java Edition, MySQL, and an in-memory buffer with persistent backing store. |
| BDB Transactional Data Store | the usual engine | [1] §5
The majority of Dynamo’s production instances use BDB Transactional Data Store. |
| (3,2,2), a couple of hundred nodes | what the measurements ran on | [1] §6
All the measurements presented in this section were taken on a live system operating with a configuration of (3,2,2) and running a couple hundred nodes with homogenous hardware configurations. |
| (3, 2, 2) | the common configuration | [1] §6
The common (N,R,W) configuration used by several instances of Dynamo is (3,2,2). |
| 3 | typical N | [1] §6
A typical value of N used by Dynamo’s users is 3. |
| R = 1, W = N | a high-performance read engine | [1] §6
Typically, these services have a high read request rate and only a small number of updates. In this configuration, typically R is set to be 1 and W to be N. |
| absolute latencies, request rates, outage lengths | what the authors withhold | [1] §1
protecting Amazon’s business interests require us to reduce some level of detail |
| 99.9% within 300 ms | the typical SLA | [1] §6.1
A typical SLA required of services that use Dynamo is that 99.9% of the read and write requests execute within 300ms. |
| around 200 ms, an order of magnitude higher | the 99.9th against the mean | [1] §6.1
the 99.9th percentile latencies are around 200 ms and are an order of magnitude higher than the averages. |
| 99.9th percentile down 5x with 1,000 objects | write buffering | [1] §6.1
This optimization has resulted in lowering the 99.9th percentile latency by a factor of 5 during peak traffic even for a very small buffer of a thousand objects |
| one replica does a durable write | the durability patch | [1] §6.1
the write operation is refined to have the coordinator choose one out of the N replicas to perform a “durable write”. |
| 99.9995% of requests, no data loss | delivered availability | [1] §6.6
applications have received successful responses (without timing out) for 99.9995% of its requests and no data loss event has occurred to date. |
| 99.94% one; 0.00057% two; 0.00047% three; 0.00009% four | divergent versions seen by the cart service in 24 hours | [1] §6.3
99.94% of requests saw exactly one version; 0.00057% of requests saw 2 versions; 0.00047% of requests saw 3 versions and 0.00009% of requests saw 4 versions. |
| concurrent writers, mostly robots | what causes divergence | [1] §6.3
the increase in the number of divergent versions is contributed not by failures but due to the increase in number of concurrent writers. |
| 30 days | Figure 4's period (text) | [1] §6.1
Figure 4 shows the average and 99.9th percentile latencies of Dynamo’s read and write operations during a period of 30 days. |
| the past year | how long in use (§1) | [1] §1
In the past year, Dynamo has been the underlying storage technology for a number of the core services in Amazon’s ecommerce platform. |
| the past two years | how long in use (§6.6) | [1] §6.6
Many Amazon internal services have used Dynamo for the past two years |
| within 15% of the average | "in balance" | [1] §6.2
a node is considered to be “in-balance”, if the node’s request load deviates from the average load by a value a less than a certain threshold (here 15%). |
| about 20% at low load, close to 10% at high | imbalance against load | [1] §6.2
during low loads the imbalance ratio is as high as 20% and during high loads it is close to 10%. |
| clients poll membership every 10 seconds | client-driven coordination | [1] §6.4
Currently clients poll a random Dynamo node every 10 seconds for membership updates. |
| 30 ms at the 99.9th percentile; 3 to 4 ms on average | what it saves | [1] §6.4
the client-driven coordination approach reduces the latencies by at least 30 milliseconds for 99.9th percentile latencies and decreases the average by 3 to 4 milliseconds. |
| a read or write to R or W nodes behaves like R-1 or W-1 | local replicas | [11] §4.2
a read or write to R or W nodes behaves like a read or write to R − 1 or W − 1 nodes. |
| up to 10 seconds | client-driven staleness | [1] §6.4
However, in the worst case the client can be exposed to stale membership for duration of 10 seconds. |
| immediate when the table looks stale | client refresh | [1] §6.4
if the client detects its membership table is stale (for instance, when some members are unreachable), it will immediately refresh its membership information. |
| N=3, R=W=1 | Cassandra default | [11] §2.3
Cassandra defaults to N =3, R=W =1 [4]. |
| N=3, R=W=1 for low latency | LinkedIn Voldemort | [11] §2.3
For applications requiring “very low latency and high availability,” LinkedIn deploys Voldemort with N =3, R=W =1. |
| any two quorums overlap | strict quorum | [11] §2.1
Informally, a strict quorum system is a quorum system with the property that any two quorums (sets) in the quorum system overlap (have non-empty intersection). |
| N=3, R=W=2 | Riak default | [11] §2.3
Riak defaults to N =3, R=W =2 [14, 15]. |
| R + W <= N | partial quorum | [11] §1.1
given N replicas and read and write quorum sizes R and W, partial quorums imply R+W ≤N . |
| a read t after commit sees the latest value | t-visibility | [11] §3.4
t-visibility is the probability that a read operation, starting t seconds after a write commits, will observe the latest value of a data item. |
| writes keep propagating after commit | Dynamo-style quorums expand | [11] §2.2
in Dynamo-style partial quorums, the write quorum size increases even after the operation returns, growing via anti-entropy [21]. |
| the first R (W) responses | what a coordinator waits for | [11] §2.2
Coordinators send all requests to all replicas but consider only the first R (W) responses. |
| four message delays: W, A, R, S | WARS | [11] §4.1
Dynamo-style quorum systems are inconsistent as a result of read and write message reordering, a product of message delays. |
| all first R responses arrived before the write | when a read is stale | [11] §4.1
reads are stale when all of the first R responses to the read request arrived at their replicas before the last (committed) write request. |
| r0 + wt + t < w0 | a replica's response is stale if | [11] §4.1
a single replica’s response is stale if r0 + wt + t < w0 for r0 drawn from R and w0 drawn from W. |
| the Wth smallest W+A | commit time | [11] §5.1
compute wt, the W th smallest value of {W[i] + A[i], i ∈ [0, N )} |
| hard to analyse | WARS and closed forms | [11] §4.1
Dynamo is straightforward to reason about and program but is difficult to analyze in a simple closed form. |
| a few lines of code | the Monte Carlo | [11] §5.1
This requires only a few lines of code. |
| Cassandra, 50,000 writes, RMSE 0.28% | the validation | [11] §5.2
Our average t-visibility prediction RMSE was 0.28% (std. dev. 0.05%, max. 0.53%) for each t ∈{1,. . . ,199} ms. |
| read repair disabled; first R responses only | how they validated | [11] §5.2
We modified Cassandra to profile WARS latencies, disabled read repair (as it is external to WARS), and, for reads, only considered the first R responses |
| exponential W: 20, 10, 5 ms; A=R=S: 10, 5, 2 ms | their injected latencies | [11] §5.2
We injected each combination of exponentially distributed W = λ ∈ {0.05, 0.1, 0.2} (means 20ms, 10ms and 5ms) and A=R=S = λ ∈ {0.1, 0.2, 0.5} (means 10ms, 5ms and 2ms) across 50,000 writes. |
| 91.22% Pareto(0.235, 10); 8.78% Exponential(1.66) | LNKD-SSD | [11] Table 3
91.22%: Pareto, xm = .235, α = 10 8.78%: Exponential, λ = 1.66 |
| 38% Pareto(1.05, 1.51); 62% Exponential(0.183) | LNKD-DISK, W | [11] Table 3
38%: Pareto, xm = 1.05, α = 1.51 62%: Exponential, λ = .183 |
| 93.9% Pareto(3, 3.35); 6.1% Exponential(0.0028) | YMMR, W | [11] Table 3
93.9%: Pareto, xm = 3, α = 3.35 6.1%: Exponential, λ = .0028 |
| 98.2% Pareto(1.5, 3.8); 1.8% Exponential(0.0217) | YMMR, A = R = S | [11] Table 3
98.2%: Pareto, xm = 1.5, α = 3.8 1.8%: Exponential, λ = .0217 |
| 75 ms on remote messages, plus LNKD-DISK | WAN | [11] §5.5
We delay remote messages by 75ms and apply LNKD-DISK delays once the command reaches a remote data center |
| independent and identically distributed | the assumption behind their fits | [11] §5.5
we assume that each latency distribution is independently, identically distributed (IID). |
| 97.4% | LNKD-SSD right after commit | [11] §5.6
Immediately after write commit, LNKD-SSD had a 97.4% probability of consistent reads |
| 43.9%; 92.5% ten ms later | LNKD-DISK right after commit | [11] §5.6
immediately after write commit, LNKD-DISK had only a 43.9% probability of consistent reads and, ten ms later, only a 92.5% probability. |
| 89.3%; 99.9% at 1364 ms | YMMR right after commit | [11] §5.6
Immediately after commit, YMMR had a 89.3% chance of consistency. |
| 33% | WAN right after commit | [11] §5.6
(33% chance immediately after commit) |
| t-visibility at p_st = .001, N = 3 | Table 4 | [11] Table 4
t-visibility for pst = .001 (99.9% probability of consistency for 50, 000 reads and writes) |
| 57.5% and 21.1% right after commit | LNKD-DISK, N = 2 and 10, R = W = 1 | [11] §5.7
With 2 replicas, LNKD-DISK has a 57.5% probability of consistent reads immediately after commit but only a 21.1% probability with 10 replicas. |
| 45.3 ms (N=2) to 53.7 ms (N=10) | LNKD-DISK, 99.9% t-visibility | [11] §5.7
the t-visibility at 99.9% probability of consistency ranges from 45.3ms for 2 replicas to 53.7ms for 10 replicas. |
| 94% at once, 99.9% after 1 ms | Figure 4, fast writes | [11] §5.3
we observe a 94% chance of consistency immediately after the write and 99.9% chance after 1ms. |
| 41% at once, 99.9% after 65 ms | Figure 4, slow writes | [11] §5.3
we observe a 41% chance of consistency immediately after write and a 99.9% chance of consistency only after 65ms. |
| 1.85 ms against 45.5 ms for 99.9% | SSD against disk | [11] §1.2
1.85ms versus 45.5ms wait time for a 99.9% probability of consistent reads |
| 81.1% lower latency for a 202 ms window | the trade | [11] §1.2
we observe an 81.1% combined read and write latency improvement at the 99.9th percentile (230 to 43.3ms) for a 202ms window of inconsistency (99.9% probability consistent reads). |
| 202 ms | YMMR, R=2, W=1 | [11] §5.6
setting R=2 and W =1 reduces t-visibility to 202ms |
| 1364 ms after commit | YMMR's 99.9% | [11] §5.6
reached a 99.9% probability of consistency 1364 ms after commit. |
| 13.6 ms | LNKD-DISK, R=2, W=1 | [11] §5.6
A 99.9% consistent t-visibility of 13.6ms reduces LNKD-DISK read and write latencies by 16.5% (2.48ms). |
| 1M reads and writes | Table 4, the sample size again | [11] Table 4
across R and W , N =3 (1M reads and writes). |
| data may be fresher than predicted | overlapping writes | [11] §4.2
with WARS, data may be fresher than predicted. |
| lower the probability of inconsistency | overlapping writes | [11] §4.2
If multiple writes overlap (that is, have overlapping periods where they are in-flight but are not committed) the probability of inconsistency decreases. |
| assumed never to occur | read repair and Merkle trees | [11] §4.2
A conservative assumption for read repair and Merkle tree exchange is that they never occur. |
| they appear as latency spikes | failures and the tail | [11] §6
Unless failures are common-case, they affect tail staleness probabilities (which appear as latency spikes in WARS). |
| a set with F failed nodes behaves like N - F | failures | [11] §6
If they are independent, a replica set of N nodes with F failed nodes behaves like an N − F replica set. |
| left for future work | hinted handoff | [11] §6
Modeling recovery semantics such as hinted handoff [20, Section 4.6] would also be useful. |
| at least one value within k versions of the latest committed | k-staleness | [11] §3.1
if, with probability 1 − psk , at least one value in any read quorum has been committed within k versions of the latest committed version when the read begins. |
| extended to multi-version staleness | probabilistic quorums | [11] §1.2
we answer these questions by expanding prior work on probabilistic quorums [49, 51] to account for multi-version staleness |
| deterministic guarantees of being within k versions | k-quorums | [11] §2.1
k-quorum systems provide deterministic guarantees that a partial quorum system will return values that are within k versions of the most recent write [10]. |
| the closed form is an upper bound | expanding quorums | [11] §3.1
For expanding partial quorum systems, this solution is an upper bound on the probability of staleness. |
| 1.88e-6 at N=100, R=W=30; "0.6" at N=3, R=W=1 | non-intersection probability | [11] §2.1
With N = 100, R = W = 30, ps = 1.88 × 10−6 [10]. However, with N = 3, R = W = 1, ps = 0.6. |
| N=3, R=W=1: 0.5, 0.703, >0.868, >0.98; N=3, R=1, W=2: 0.6, 0.8, >0.995 | their worked values | [11] §3.1
When N =3, R=W =1, this means that the probability of returning a version within 2 versions is 0.5, within 3 versions, 0.703, 5 versions, > 0.868, and 10 versions, > 0.98. When N =3, R=1, W =2 (or, equivalently, R=2, W =1), these probabilities increase: k=1 → 0.6, k=2 → 0.8, and k=5 →> 0.995. |
| cannot order updates at one server | per-server entries | [8] §3.2
However, this approach cannot track causality among updates submitted to the same server. |
| plausible clocks | where Dynamo falls | [8] §3.2
The Dynamo system uses one entry per replica node and thus falls into this category. |
| one concurrent update is lost | the consequence | [8] §3.2
In practice a last writer wins policy was enforced with respect to concurrent updates handled in the same replica node, and, in this case, one concurrent update was lost. |
| one entry per server holding a replica | what dotted version vectors need | [8] Abstract
it maintains information that grows linearly only with the number of servers that register updates for a given data element, bounded by the degree of replication. |