Live data from Hacker News

Why Cassandra Doesn't Need Vector Clocks

datastax.com

51–60 of 69 posts

Re: Why Cassandra Doesn't Need Vector Clocks

#51
post #50

Earlier quoted context omitted.

The difference is that all the cells with the same `id` would belong to the same partition and stored together, so you'd be able to write them atomically and read them together cheaply in a single operation. What marshray suggested would look like this: create table bucket.users (name text, field text, value text, primary key ((name, field))); - with a composite partition key. Then you'd have two separate single-cell…

you'd be able to write them atomically To clarify, this is only the case if you use Cassandra 2.0 transactions; normal batched writes are not atomic in the sense you're probably thinking.

No batching here, just single-partition, two cell update. Atomic, but not isolated in the way you define isolation in your gist.

Re: Why Cassandra Doesn't Need Vector Clocks

#52
post #47
post #37

Earlier quoted context omitted.

> As far as I can determine in testing with Jepsen, there are no cases where one can safely (e.g. in a way which guarantees some causal connection of your write to a future state of the system) update a cell in Cassandra without a strong timestamp coordinator: either an external system like Zookeeper, or Cassandra 2.0 paxos transactions. It depends on what you mean by "guarantees". In most real world systems, if you…

The world of consistency is rich: not all systems require serializability, linearizability, or any one write winning. It might be interesting to skim http://pmg.csail.mit.edu/papers/adya-phd.pdf , http://ftp.research.microsoft.com/pub/tr/tr-95-51.pdf , and pagesperso-systeme.lip6.fr/Marc.Shapiro/papers/RR-6956.pdf‎ for a taste.

(asking for my self and other readers of this thread)

is LWW = Last Write Wins?

Re: Why Cassandra Doesn't Need Vector Clocks

#53

Cassandra counters once were implemented as a blazing-fast vector-clock patch [1,2] that did not involve read-before-write on update. The biggest (IMO) downside is that it did not support decrements. So Cassandra tech leadership decided [2] to implement counters as "read, increment, write." However, that came with two major downsides: 1) counter updates were now no longer replayable--so if you experience an update ti…

Hypertable has crazy fast increments-decrements(without reads). If the column is in memory it is updated on the spot. Else multiple values are inserted and merged on read or compaction. But it is a little different from cassandra, more similar to hbase.

Re: Why Cassandra Doesn't Need Vector Clocks

#54
post #48
post #42

Earlier quoted context omitted.

Okay, you do raise a good point about what happens if the timestamps happen to be precisely identical. Most of the scenarios I've had where the precise same timestamp was at all likely, the updates would also have been identical. If you want to have overlapping cells resolving highly concurrent writes (not even using wide rows to make precisely concurrent writes go to different cells anyway), Cassandra is probably no…

if that were considered a likely scenario When timestamps are selected by the Cassandra nodes, I can replicate this failure in 2% to 5% of writes. When timestamps collide, I can replicate this failure in 99.9% of writes. Given that the whole point of isolation is to provide invariants during concurrent modification , it doesn't make any sense to claim that a write is transactionally isolated only insofar as it is not…

> I can replicate this failure in 2% to 5% of writes.

Yeah, I'm curious about how you achieved those numbers.

Your test that gets that 2-5% of writes (though your docs say 7.5%) to be messed up... what is really is measuring is the probability that out of 5 concurrent clients writing to 4 servers, at least two will finish writing to a row with the exact same timestamp... AND that they will be the LAST ones to write to that row. If just one of those clients ends up just a hair behind the other four, then you should register 0 collisions.

What is even weirder is your benchmark takes 100 seconds to complete what amounts to 5000 writes, or averaging a rate of 50 writes per second, 10 writes per client per second. Those are pathetic numbers for a one node Cassandra cluster, let alone a four node one. WTF is going on here?

Even more confusing, you are writing with ANY consistency, which means that in many cases those writes will be stamped and committed on different nodes, yet somehow getting the same timestamp. Odds on this seem... highly suspect. It almost seems like your clock only has 1 second resolution, which is weird. Have you checked the writetime timestamps on your records?

I've done writes at much higher rates where we recorded the timestamps of every single write operation. We've yet to get the same timestamp on two operations.

I also see Cassandra timeouts while writing with consistency ANY, yet are still somehow getting timeouts with this operation. That really screams to me that the cluster is truly messed up.

Now, as you say, if you control the timestamps, you get collisions 99.9% of the time. I don't even get why it isn't just straight up 100% for that case.

> Given that the whole point of isolation is to provide invariants during concurrent modification

I think it is fair to say that you don't have transaction isolation if the timestamps are exactly the same. That is just an exceedingly low probability event unless you have a LOT of transactions per second.

I'd dump the "writetime(a), writetime(b)" values to get an idea of what is going on there.... something smells and there is a lot less cardinality in those timestamps than I'd expect.

Re: Why Cassandra Doesn't Need Vector Clocks

#55
post #50

Earlier quoted context omitted.

The difference is that all the cells with the same `id` would belong to the same partition and stored together, so you'd be able to write them atomically and read them together cheaply in a single operation. What marshray suggested would look like this: create table bucket.users (name text, field text, value text, primary key ((name, field))); - with a composite partition key. Then you'd have two separate single-cell…

you'd be able to write them atomically To clarify, this is only the case if you use Cassandra 2.0 transactions; normal batched writes are not atomic in the sense you're probably thinking.

Actually, even in Cassandra 1.2, batch operations were atomic unless otherwise specified.

Re: Why Cassandra Doesn't Need Vector Clocks

#56
post #47

Earlier quoted context omitted.

The world of consistency is rich: not all systems require serializability, linearizability, or any one write winning. It might be interesting to skim http://pmg.csail.mit.edu/papers/adya-phd.pdf , http://ftp.research.microsoft.com/pub/tr/tr-95-51.pdf , and pagesperso-systeme.lip6.fr/Marc.Shapiro/papers/RR-6956.pdf‎ for a taste.

(asking for my self and other readers of this thread) is LWW = Last Write Wins?

Yes.

Re: Why Cassandra Doesn't Need Vector Clocks

#57
post #49

Earlier quoted context omitted.

In Cassandra the second update agreed upon by the cluster would "win", so either (X1,Y1) or (X2,Y2). Since there is no clock mechanism there is no way for the cluster to see that the data has changed since the requester decided it wanted to update the value.

Rows are not isolated. You might see (X1, Y1), (X1, Y2), (X2, Y1), or (X2, Y2) if timestamps happen to conflict. https://gist.github.com/aphyr/6402464

Oh wow, that is bad. I was assuming that guarantee of row isolation was valid.

Re: Why Cassandra Doesn't Need Vector Clocks

#58
post #54
post #48

Earlier quoted context omitted.

if that were considered a likely scenario When timestamps are selected by the Cassandra nodes, I can replicate this failure in 2% to 5% of writes. When timestamps collide, I can replicate this failure in 99.9% of writes. Given that the whole point of isolation is to provide invariants during concurrent modification , it doesn't make any sense to claim that a write is transactionally isolated only insofar as it is not…

> I can replicate this failure in 2% to 5% of writes. Yeah, I'm curious about how you achieved those numbers. Your test that gets that 2-5% of writes (though your docs say 7.5%) to be messed up... what is really is measuring is the probability that out of 5 concurrent clients writing to 4 servers, at least two will finish writing to a row with the exact same timestamp... AND that they will be the LAST ones to write t…

Yeah, I'm curious about how you achieved those numbers.

Jepsen's code is open source (http://github.com/aphyr/jepsen) and I've written extensively about the techniques involved; see http://aphyr.com/tags/jepsen for details. Cassandra work is upcoming; no formal writeup yet.

Your test that gets that 2-5% of writes (though your docs say 7.5%) to be messed up...

Sorry, 2-5% was my mistake. Been playing around with the parameter space; numbers vary a bit.

what is really is measuring is the probability that out of 5 concurrent clients writing to 4 servers, at least two will finish writing to a row with the exact same timestamp... AND that they will be the LAST ones to write to that row. If just one of those clients ends up just a hair behind the other four, then you should register 0 collisions.

In a Dynamo system, a.) there is no such thing as "time", b.) there is no such thing as "last", and c.) causality tracking beats everything. Doesn't matter what order you do the writes in; timestamps (and/or vclocks in Voldemort/Riak) take precedence.

What is even weirder is your benchmark takes 100 seconds to complete what amounts to 5000 writes, or averaging a rate of 50 writes per second, 10 writes per client per second. Those are pathetic numbers for a one node Cassandra cluster, let alone a four node one. WTF is going on here?

Each client in the Jepsen test harness is (independently) scheduling n writes per second. Jepsen schedules its writes this way to a.) avoid measuring an overloaded system, b.) produce results which are somewhat comparable between runs, and c.) measure results over changing underlying dynamics--in this case, a network partition.

Even more confusing, you are writing with ANY consistency, which means that in many cases those writes will be stamped and committed on different nodes, yet somehow getting the same timestamp. Odds on this seem... highly suspect. It almost seems like your clock only has 1 second resolution, which is weird.

There's an interesting probability anecdote called the Birthday Paradox, which says that if you get 30 people in a room, chances are good that 2 will share the same birthday. At ten uniformly distributed writes a second, the probability of a timestamp collision is 0.44%... in any given second. Chances of a collision after a thousand seconds of runtime are 99.9999%. If you push 100 writes per second, collision probability is 50% in any second. If you push only 2 writes every second, you should expect to see a collision once every few days. How long-lived is that collision? It depends on the distribution of writes over time, and on the network, but you can work out a mean free path.

TL;DR: microsecond timestamps do not provide sufficient entropy for uniqueness constraints over common workloads.

I also see Cassandra timeouts while writing with consistency ANY, yet are still somehow getting timeouts with this operation. That really screams to me that the cluster is truly messed up.

The timeouts in this case are, I think, a Cassandra bug (or expected behavior) when partitions occur. Last I heard from jbellis, it wasn't clear what Cassandra should do under these conditions, but I think he was leaning towards allowing the local hint to count as success always.

Now, as you say, if you control the timestamps, you get collisions 99.9% of the time. I don't even get why it isn't just straight up 100% for that case.

The reason not all writes result in conflict with identical timestamps is, I suspect, due to that transitional period during the beginning of the network partition.

Re: Why Cassandra Doesn't Need Vector Clocks

#59
post #50

Earlier quoted context omitted.

The difference is that all the cells with the same `id` would belong to the same partition and stored together, so you'd be able to write them atomically and read them together cheaply in a single operation. What marshray suggested would look like this: create table bucket.users (name text, field text, value text, primary key ((name, field))); - with a composite partition key. Then you'd have two separate single-cell…

you'd be able to write them atomically To clarify, this is only the case if you use Cassandra 2.0 transactions; normal batched writes are not atomic in the sense you're probably thinking.

They are atomic, they are not isolated. Those are two different properties. The "A" vs the "I" in ACID. http://en.wikipedia.org/wiki/ACID

Edit: Actually, they are isolated in the sense of ACID, doesn't matter what order you do to operations, the answer will be the same. But not isolated the way you want isolated described.

Re: Why Cassandra Doesn't Need Vector Clocks

#60
post #58
post #54

Earlier quoted context omitted.

> I can replicate this failure in 2% to 5% of writes. Yeah, I'm curious about how you achieved those numbers. Your test that gets that 2-5% of writes (though your docs say 7.5%) to be messed up... what is really is measuring is the probability that out of 5 concurrent clients writing to 4 servers, at least two will finish writing to a row with the exact same timestamp... AND that they will be the LAST ones to write t…

Yeah, I'm curious about how you achieved those numbers. Jepsen's code is open source ( http://github.com/aphyr/jepsen ) and I've written extensively about the techniques involved; see http://aphyr.com/tags/jepsen for details. Cassandra work is upcoming; no formal writeup yet. Your test that gets that 2-5% of writes (though your docs say 7.5%) to be messed up... Sorry, 2-5% was my mistake. Been playing around with the…

bq. I also see Cassandra timeouts while writing with consistency ANY, yet are still somehow getting timeouts with this operation. That really screams to me that the cluster is truly messed up.

This was a issue with atomic batches and CL.ANY we've fixed since the test.

https://issues.apache.org/jira/browse/CASSANDRA-5967

Post reply on HN