Data partitioning is crucial for distributing data across multiple nodes in a distributed key-value store system to achieve scalability and efficient data access. Consistent hashing is a popular technique used for data partitioning in distributed systems.
Data Replication Strategies:
Data replication ensures fault tolerance and high availability by storing multiple copies of data across different nodes in the system. Common data replication strategies include:
For our design we will go with Quorum-based replication, this will be explained in detail in the detailed component design section.
Consistency and Types of Consistency:
Consistency in a distributed key-value store system refers to the agreement of data across multiple replicas. Different consistency models offer varying levels of guarantees:
Strong consistency is usually achieved by forcing a replica not to accept new reads/writes until every replica has agreed on current write. This approach is not ideal for highly available systems because it could block new operations. Dynamo and Cassandra adopt eventual consistency, which is our recommended consistency model for our key-value store.
Below sequence diagram is for how user makes basic operations.
Replication gives high availability but causes inconsistencies among replicas. Versioning and vector locks are used to solve inconsistency problems. Versioning means treating each data modification as a new immutable version of data. Before we talk about versioning, let us use an example to explain how inconsistency happens:
lets assume there are 2 nodes, both replica nodes n1 and n2 have the same value. Let us call this value the original value. Server 1 and server 2 get the same value for get(“name”) operation
Next, server 1 changes the name to “johnSanFrancisco”, and server 2 changes the name to “johnNewYork” as shown in Figure 8. These two changes are performed simultaneously. Now, we have conflicting values, called versions v1 and v2.
In this example, the original value could be ignored because the modifications were based on it. However, there is no clear way to resolve the conflict of the last two versions. To resolve this issue, we need a versioning system that can detect conflicts and reconcile conflicts. A vector clock is a common technique to solve this problem.
Let us examine how vector clocks work.
A vector clock is a [server, version] pair associated with a data item. It can be used to check if one version precedes, succeeds, or in conflict with others.
Assume a vector clock is represented by D([S1, v1], [S2, v2], …, [Sn, vn]), where D is a data item, v1 is a version counter, and s1 is a server number, etc. If data item D is written to server Si, the system must perform one of the following tasks.
The above abstract logic is explained with a concrete example .
Using vector clocks, it is easy to tell that a version X is an ancestor (i.e. no conflict) of version Y if the version counters for each participant in the vector clock of Y is greater than or equal to the ones in version X. For example, the vector clock D([s0, 1], [s1, 1])] is an ancestor of D([s0, 1], [s1, 2]). Therefore, no conflict is recorded.
Similarly, you can tell that a version X is a sibling (i.e., a conflict exists) of Y if there is any participant in Y's vector clock who has a counter that is less than its corresponding counter in X. For example, the following two vector clocks indicate there is a conflict: D([s0, 1], [s1, 2]) and D([s0, 2], [s1, 1]).
Even though vector clocks can resolve conflicts, there are two notable downsides.
This can lead to inefficiencies in reconciliation because the descendant relationship cannot be determined accurately. However, based on Dynamo paper, Amazon has not yet encountered this problem in production; therefore, it is probably an acceptable solution for most companies.
Quorum-based replication is a data replication strategy commonly used in distributed systems to balance consistency, availability, and partition tolerance. In quorum-based replication, read and write operations require acknowledgment from a subset of replicas known as a quorum. By adjusting the quorum size, system designers can control the trade-off between consistency and availability.
Example of Quorum-Based Replication:
Consider a distributed key-value store system with a total of 5 replicas (nodes) replicating data across the cluster. In this example, we'll explore how quorum-based replication works for read and write operations.
Benefits of Quorum-Based Replication:
Overall, quorum-based replication offers a flexible and robust approach to data replication in distributed key-value store systems, allowing system designers to tailor consistency levels to meet the specific needs of their applications.
Handling data center outages is crucial for ensuring the availability and reliability of a distributed key-value store system, especially in scenarios such as power outages, network failures, natural disasters, or other unforeseen events. Here are some strategies and considerations for building a system capable of handling data center outages:
Load balancing is a critical component in distributed systems to evenly distribute incoming requests across multiple servers or nodes, ensuring optimal resource utilization, scalability, and fault tolerance. There are several load balancing strategies available, each with its own advantages, disadvantages, and use cases. Let's discuss some common load balancing strategies:
Here are a few trade-offs that we have to do with each tech choice we make.
Below are 3 improvements that we can make as per our design.