"Eventual Consistency" vs "Strong Eventual Consistency" vs "Strong Consistency"?

I came across the concept of "Strong Eventual Consistency" . Is it supposed to be stronger than "Eventual Consistency" but weaker than "Strong Consistency"? Could someone explain the differences among these three concepts with applicable examples?

http://en.wikipedia.org/wiki/Eventual_consistency#Strong_Eventual_Consistency http://en.wikipedia.org/wiki/Conflict-free_replicated_data_type

Many thanks.


DISCLAIMER: The text below should give you a rough idea about the differences among Eventual Consistency, Strong Eventual Consistency and Strong Consistency. But they are in some way an over-simplification. So take them with a grain of salt ;)


First things first: when we talk about consistency we refer to an scenario where different entities (nodes) have their own copy of some data object. Now, conflicts arise because each node can update its own copy (e.g. because there are clients, each one connected to some node, asking them to do so), so if I read the data from different nodes I'll see different values. This is where Eventual Consistency (EC), Strong Eventual Consistency (SEC) and Strong Consistency (SC) come into play.

Eventual Consistency Conflicts can arise, but nodes communicate each other their changes to solve those conflicts, so in time they agree upon the definitive value. Thus, if no more changes are applied to the data for a certain period, then all nodes will agree in the data value (i.e. they will eventually agree) so readers of data will eventually see the same value.

Example: two nodes A and B (nA and nB) have each one copy of a string, which is update with operations read() and write(string). Let's say each one has its own client (cliA and cliB). Let's say that initially both nodes store the same value "Joe", but at some moment nA updates it to "Frank" (calls write("Frank")). Then nA will tell nB that the value has been updated; as both values differ a conflict has arisen but in can be solved using some policy (for example last-write-wins) so nB finally updates its record also to "Frank". Before the conflict is resolved cliA and cliB will see different versions of the data (the read() op result will differ), but eventually both will see the same value again.

Keep in mind that if both nodes update their value simultaneously then conflict resolution is still possible but more complicated. This is where SEC shines.

Strong Eventual Consistency This is a special case of EC, that is valid only for certain data types.

Let's assume that the data object shared is a counter, and updates are made by add(int value) and substract(int value) operations. In this case, the order in which we apply updates does not matter! So if both nA and nB start with a counter value of 0, and if then nA runs add(10) and nB runs substract(5) (simultaneosly), they only need to send the update operation to each other without caring for conflict resolution, eventually it is ensured that they will reach the same value (remember that, in contrast, in the previous example for EC some conflict resolution could be required)!

Unfortunately SEC is only applicable in certain data types and operations that have specific properties (commutativity and others). Such data types are denoted Conflict-free Replicated Data Type (CRDT) .

Strong consistency Quite different to the other two. Here it is a requirement that upon update operations all nodes agree on the new value before making the new value visible to clients. That way updates are visible to all clients 'at the same time', so they will read the same value at all times. Now this introduces the requirement for some blocking in update operations. Both in EC and SEC an update operation was over as soon as the local copy was updated (then the operation was broadcasted to the other nodes). Here a client update does not return until all nodes have agreed upon the data value, and while this is done all accesses to any copy of that data are 'locked' (so other clients reads are blocked). In our example for EC, if cliA runs write("Frank"), cliA will be blocked until the update is agreed by both nA and nB, and then it will made visible for both cliA and cliB at the same time, i.e. the read() operation should return the same value from then on.