diff --git a/akka-distributed-data/src/main/scala/akka/cluster/ddata/LWWMap.scala b/akka-distributed-data/src/main/scala/akka/cluster/ddata/LWWMap.scala index 86ee1f5c11..bb003f60d2 100644 --- a/akka-distributed-data/src/main/scala/akka/cluster/ddata/LWWMap.scala +++ b/akka-distributed-data/src/main/scala/akka/cluster/ddata/LWWMap.scala @@ -31,6 +31,13 @@ object LWWMap { * use a timestamp value based on something else, for example an increasing version number * from a database record that is used for optimistic concurrency control. * + * The `defaultClock` is using max value of `System.currentTimeMillis()` and `currentTimestamp + 1`. + * This means that the timestamp is increased for changes on the same node that occurs within + * the same millisecond. It also means that it is safe to use the `LWWMap` without + * synchronized clocks when there is only one active writer, e.g. a Cluster Singleton. Such a + * single writer should then first read current value with `ReadMajority` (or more) before + * changing and writing the value with `WriteMajority` (or more). + * * For first-write-wins semantics you can use the [[LWWRegister#reverseClock]] instead of the * [[LWWRegister#defaultClock]] * diff --git a/akka-distributed-data/src/main/scala/akka/cluster/ddata/LWWRegister.scala b/akka-distributed-data/src/main/scala/akka/cluster/ddata/LWWRegister.scala index 77eca287f5..5f411c12e4 100644 --- a/akka-distributed-data/src/main/scala/akka/cluster/ddata/LWWRegister.scala +++ b/akka-distributed-data/src/main/scala/akka/cluster/ddata/LWWRegister.scala @@ -85,6 +85,13 @@ object LWWRegister { * use a timestamp value based on something else, for example an increasing version number * from a database record that is used for optimistic concurrency control. * + * The `defaultClock` is using max value of `System.currentTimeMillis()` and `currentTimestamp + 1`. + * This means that the timestamp is increased for changes on the same node that occurs within + * the same millisecond. It also means that it is safe to use the `LWWRegister` without + * synchronized clocks when there is only one active writer, e.g. a Cluster Singleton. Such a + * single writer should then first read current value with `ReadMajority` (or more) before + * changing and writing the value with `WriteMajority` (or more). + * * For first-write-wins semantics you can use the [[LWWRegister#reverseClock]] instead of the * [[LWWRegister#defaultClock]] * diff --git a/akka-docs/rst/java/distributed-data.rst b/akka-docs/rst/java/distributed-data.rst index bdc0bab88a..ac778d0b0a 100644 --- a/akka-docs/rst/java/distributed-data.rst +++ b/akka-docs/rst/java/distributed-data.rst @@ -337,13 +337,6 @@ values. .. includecode:: code/docs/ddata/DistributedDataDocTest.java#ormultimap -Note that ``LWWRegister`` and therefore ``LWWMap`` relies on synchronized clocks and should only be used -when the choice of value is not important for concurrent updates occurring within the clock skew. - -Instead of using timestamps based on ``System.currentTimeMillis()`` time it is possible to -use a timestamp value based on something else, for example an increasing version number -from a database record that is used for optimistic concurrency control. - When a data entry is changed the full state of that entry is replicated to other nodes, i.e. when you update a map the whole map is replicated. Therefore, instead of using one ``ORMap`` with 1000 elements it is more efficient to split that up in 10 top level ``ORMap`` entries @@ -352,6 +345,10 @@ trade-off that different entries may not be replicated at the same time and you inconsistencies between related entries. Separate top level entries cannot be updated atomically together. +Note that ``LWWRegister`` and therefore ``LWWMap`` relies on synchronized clocks and should only be used +when the choice of value is not important for concurrent updates occurring within the clock skew. Read more +in the below section about ``LWWRegister``. + Flags and Registers ------------------- @@ -380,6 +377,13 @@ from a database record that is used for optimistic concurrency control. For first-write-wins semantics you can use the ``LWWRegister#reverseClock`` instead of the ``LWWRegister#defaultClock``. +The ``defaultClock`` is using max value of ``System.currentTimeMillis()`` and ``currentTimestamp + 1``. +This means that the timestamp is increased for changes on the same node that occurs within +the same millisecond. It also means that it is safe to use the ``LWWRegister`` without +synchronized clocks when there is only one active writer, e.g. a Cluster Singleton. Such a +single writer should then first read current value with ``ReadMajority`` (or more) before +changing and writing the value with ``WriteMajority`` (or more). + Custom Data Type ---------------- diff --git a/akka-docs/rst/scala/distributed-data.rst b/akka-docs/rst/scala/distributed-data.rst index 7d48ec8cbb..04aa00b2f6 100644 --- a/akka-docs/rst/scala/distributed-data.rst +++ b/akka-docs/rst/scala/distributed-data.rst @@ -337,13 +337,6 @@ values. .. includecode:: code/docs/ddata/DistributedDataDocSpec.scala#ormultimap -Note that ``LWWRegister`` and therefore ``LWWMap`` relies on synchronized clocks and should only be used -when the choice of value is not important for concurrent updates occurring within the clock skew. - -Instead of using timestamps based on ``System.currentTimeMillis()`` time it is possible to -use a timestamp value based on something else, for example an increasing version number -from a database record that is used for optimistic concurrency control. - When a data entry is changed the full state of that entry is replicated to other nodes, i.e. when you update a map the whole map is replicated. Therefore, instead of using one ``ORMap`` with 1000 elements it is more efficient to split that up in 10 top level ``ORMap`` entries @@ -352,6 +345,10 @@ trade-off that different entries may not be replicated at the same time and you inconsistencies between related entries. Separate top level entries cannot be updated atomically together. +Note that ``LWWRegister`` and therefore ``LWWMap`` relies on synchronized clocks and should only be used +when the choice of value is not important for concurrent updates occurring within the clock skew. Read more +in the below section about ``LWWRegister``. + Flags and Registers ------------------- @@ -380,6 +377,13 @@ from a database record that is used for optimistic concurrency control. For first-write-wins semantics you can use the ``LWWRegister#reverseClock`` instead of the ``LWWRegister#defaultClock``. +The ``defaultClock`` is using max value of ``System.currentTimeMillis()`` and ``currentTimestamp + 1``. +This means that the timestamp is increased for changes on the same node that occurs within +the same millisecond. It also means that it is safe to use the ``LWWRegister`` without +synchronized clocks when there is only one active writer, e.g. a Cluster Singleton. Such a +single writer should then first read current value with ``ReadMajority`` (or more) before +changing and writing the value with ``WriteMajority`` (or more). + Custom Data Type ----------------