I'm not familiar with CRDTs, though I'll look into them -- thanks for the pointer. To clarify my original idea/question, the following example:
Yeah sure, imagine you're trying to compute count of how many times you've seen something. This is a SUM aggregate.
I assume the reason the author said "Ensuring aggregates are essentially single-threaded entities is a must" was because they are mutating a single key, if two different processes try to change the same value, you get inconsistent state.
An example of this would be:
Current K/V Pair: "A" -> 2
Modifier 1: Reads "A", gets 2
Modifier 2: Reads "A", gets 2
Modifier 1: Writes "A" -> 3
Modifier 2: Writes "A" -> 3
This means our sum is now inconsistent, as we would expect the value to be 4 in a single-threaded system.
However, because we are doing a sum, we can use commutativity to remove this conflict. Instead of each writer trying to write to a single key, you might make a compound key (Id, )
Current Value Pairs: [("A", "Modifier 1") -> 1, ("A", "Modifier 2") -> 1]
Modifier 1: Reads ("A", "Modifier 1"), gets 1
Modifier 2: Reads ("A", "Modifier 2"), gets 1
Modifier 1: Writes ("A", "Modifier 1") -> 2
Modifier 2: Writes ("A", "Modifier 2") -> 2
Then, a reader could just ask for all the keys with the prefix "A" (This is the range query). So a reader gets back (2, 2), which then can now merge into 4 as SUM is a commutative operation. Because the reader is taking care of the final aggregation step, there's no concurrency conflict so you can get away with having any number of writers as long as the read and read-side computation is cheap enough.
Some aggregates are commutative only in certain forms, like AVERAGE. To explain further, if one writer says the AVERAGE is 5 and another says it is 7, I can't combine those to say that the global average is 6.
However, if each writer stores both SUM and COUNT, I can use (COUNT1 + COUNT2)/(SUM1 + SUM2). This is because division doesn't commute, so I have to delay the non-commutative operation until the reader if I want to be able to merge two data sources.
Edited: Formatting