[ 
https://issues.apache.org/jira/browse/CASSANDRA-5062?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13619810#comment-13619810
 ] 

Sylvain Lebresne commented on CASSANDRA-5062:
---------------------------------------------

bq. it's supposed to reply with the ballot of a previously accepted value

Ok. But then I think we have the following problem (at least I don't see what 
prevent this from happening): say you have 3 replica A, B, C and I'll use MRC 
for the 'most-recently committed' value, IPB for 'in-progress ballot' and IPU 
for 'in-porgress update'. I'll also use t0, t1, ... for ballots (where t0 < t1 
< t2 ...), P0, P1, ... for proposers (any coordinator) and c0, c1, c2 for 
different column names (with say int values) inside the same row.

* At t0, P0 wants to do cas(c0, null, 3). He prepares, gets all acks and 
propose c0=3 that all node acks. However, C dies before receiving the commit.  
At this point, we have the following states ():
|| Node  || MRC || IPB || IPC || In storage ||
|  A     |  t0  |      |      |   c0=3      |
|  B     |  t0  |      |      |   c0=3      |
|  C     |      |  t0  |  c0=3|             |
* At t1, P1 wants to do cas(c1, null, 5). He prepares and proposes with A and B 
answering (so on prepare he gets no IPB). However, during commit, B fails and 
only A gets it. At that point, C comes back up (but don't get the commit).  The 
state is now:
|| Node  || MRC || IPB || IPC || In storage ||
|  A     |  t1  |      |      |   c0=3,c1=5 |
|  B     |  t0  |  t1  |  c1=5|   c0=3      |
|  C     |      |  t0  |  c0=3|             |
* At t2, P3 wants to do cas(c2, null, 7). He gets back from A and C. From A, he 
gets MRC=t1 and from B, IPB=t0. So IPB < MRC, and the proposer decides he can 
proceed with his own value, because C is old and irrelevant. He thus propose, 
both A and C acknowledge and both get the final commit. The state is now:
|| Node  || MRC || IPB || IPC || In storage      ||
|  A     |  t2  |      |      |   c0=3,c1=5,c2=7 |
|  B     |  t0  |  t1  |  c1=5|   c0=3           |
|  C     |  t2  |      |      |   c2=7           |
* Now B comes back. Then, at t3, P3 wants to do cas(c2, 7, 9). Everyone replica 
gets all message, the cas apply (whether B answer or not, since it's IPB is now 
"too old") and we end-up in the following state:
|| Node  || MRC || IPB || IPC || In storage      ||
|  A     |  t3  |      |      |   c0=3,c1=5,c2=9 |
|  B     |  t3  |      |      |   c0=3,c2=9      |
|  C     |  t3  |      |      |   c2=9           |
* Now at t4, P4 wants to do cas(c1, null, 3). The prepare will work in any 
case, and so P4 will read the value of c1 at QUORUM before the propose. 
However, if B and C answer first, then we don't have the correct value. We get 
c1 = null, making the CAS apply, while in theory c1 = 5 so the CAS shouldn't 
apply.

In plain english, I think the problem is that we use successful round of CAS to 
serialize your CAS (which is standard). However, we delete the CAS state of the 
previous round pretty much as soon as one node has learn the value. We do 
replay the previous round if some of the replica that answer to prepare are on 
that previous round, but if replica are on an older round (than the previous 
one), we do move one, and thus might erase state while only one replica has 
learn, which is not ok.

One option could be to ensure that a quorum of node has learned before starting 
a new round (i.e. accepting a new value on the prepare phase). But I think this 
require to keep the last-recently-committed 'value' too.

                
> Support CAS
> -----------
>
>                 Key: CASSANDRA-5062
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-5062
>             Project: Cassandra
>          Issue Type: New Feature
>          Components: API, Core
>            Reporter: Jonathan Ellis
>             Fix For: 2.0
>
>         Attachments: half-baked commit 1.jpg, half-baked commit 2.jpg, 
> half-baked commit 3.jpg
>
>
> "Strong" consistency is not enough to prevent race conditions.  The classic 
> example is user account creation: we want to ensure usernames are unique, so 
> we only want to signal account creation success if nobody else has created 
> the account yet.  But naive read-then-write allows clients to race and both 
> think they have a green light to create.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to