cassandra-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From DuyHai Doan <doanduy...@gmail.com>
Subject Re: Consistency when adding data to collections concurrently?
Date Sat, 12 Nov 2016 16:40:06 GMT
"doing mapper.save() will do an insert rather than an update? " --> Yes

The java driver mapper has no update method. To do an update you need to
use the Accessor and roll out your own update statement

On Sat, Nov 12, 2016 at 5:37 PM, Ali Akhtar <ali.rac200@gmail.com> wrote:

> Just to be clear, doing mapper.save() will do an insert rather than an
> update?
>
> On Sat, Nov 12, 2016 at 9:36 PM, Andrew Tolbert <
> andrew.tolbert@datastax.com> wrote:
>
>> I believe you are correct that the implementation taking the Set is the
>> right one to use.
>>
>> On Sat, Nov 12, 2016 at 9:44 AM Ali Akhtar <ali.rac200@gmail.com> wrote:
>>
>>> Or it could even take Set<label> as the first bound var:
>>>
>>> void addLabel(Set<Label> label, String id);
>>>
>>>
>>> On Sat, Nov 12, 2016 at 8:41 PM, Ali Akhtar <ali.rac200@gmail.com>
>>> wrote:
>>>
>>> Andrew,
>>>
>>> I was thinking about setting up an accessor with that query and a bound
>>> variable ? which binds to the instance being added, e.g:
>>>
>>> @Query("UPDATE my_table SET labels = labels + ? WHERE id = ?")
>>> void addLabel(Label label, String id);
>>>
>>> Will that  work?
>>>
>>> On Sat, Nov 12, 2016 at 8:38 PM, Andrew Tolbert <
>>> andrew.tolbert@datastax.com> wrote:
>>>
>>> You can do it in a SimpleStatement assuming you provide the CQL exactly
>>> as you provided, but in a PreparedStatement it will not work because cql
>>> prohibits provide bind values in collection literals.  For it to work you
>>> could provide a List of UDT values in a bound prepared statement, i.e.:
>>>
>>>     UserType udtType = cluster.getMetadata().getKeysp
>>> ace("k").getUserType("u");
>>>     UDTValue value = udtType.newValue();
>>>     value.setString(0, "data");
>>>
>>>     PreparedStatement p0 = session.prepare("UPDATE my_table SET labels =
>>> labels + ? where id = ?");
>>>     BoundStatement b0 = p0.bind(*Lists.newArrayList(value)*, 0);
>>>     session.execute(b0);
>>>
>>> Thanks,
>>> Andy
>>>
>>> On Sat, Nov 12, 2016 at 9:02 AM, Ali Akhtar <ali.rac200@gmail.com>
>>> wrote:
>>>
>>> Looks like the trick was to use [] around the udt value literal.
>>>
>>> Any way to do this using the java driver?
>>>
>>> On Sat, Nov 12, 2016 at 7:58 PM, Ali Akhtar <ali.rac200@gmail.com>
>>> wrote:
>>>
>>> Changing the double quotes to single quotes gives:
>>>
>>> UPDATE my_table SET labels = labels + {id: 'foo'} where id = '';
>>>
>>> InvalidRequest: Error from server: code=2200 [Invalid query]
>>> message="Invalid user type literal for labels of type list<frozen<label>>"
>>>
>>>
>>> On Sat, Nov 12, 2016 at 7:50 PM, Ali Akhtar <ali.rac200@gmail.com>
>>> wrote:
>>>
>>> The question is about appending to a set of frozen<udt> and how to do
>>> that while avoiding the race condition.
>>>
>>> If I run:
>>>
>>>  UPDATE my_table SET labels = labels + {id: "foo"} where id = 'xx';
>>>
>>> I get:
>>>
>>> SyntaxException: line 1:57 no viable alternative at input '}' (...=
>>> labels + {id: ["fo]o"}...)
>>>
>>> Here labels is set<frozen<label>>
>>>
>>> On Sat, Nov 12, 2016 at 7:40 PM, Vladimir Yudovin <vladyu@winguzone.com>
>>> wrote:
>>>
>>> If I used consistency = ALL both when getting the record, and when
>>> saving the record, will that avoid the race condition?
>>> If I use consistency level = all, will that cause it to end up with
>>> [1,2]?
>>> No. Even if you have only one host it's possible that two threads first
>>> both read data and than overwrite existing value one by one.
>>>
>>> The list is actually of a list<frozen<my_udt>> and not a text (I
used
>>> text for simplification, apologies).
>>> In that case, will updates still merge the list values instead of
>>> overwriting them?
>>> Do you mean UPDATE cql operation? Yes, it adds new values to list,
>>> allowing duplicates.
>>>
>>> When setting a new value to a list, C* will do a read-delete-write
>>> internally e.g. read the current list, remove all its value (by a range
>>> tombstone) and then write the new list.
>>> As I mentioned duplicates are allowed in LIST, and as DOC says:
>>>
>>> These update operations are implemented internally without any
>>> read-before-write. Appending and prepending a new element to the list
>>> writes only the new element.
>>>
>>> Only when using index
>>>
>>> When you add an element at a particular position, Cassandra reads the
>>> entire list, and then writes only the updated element. Consequently, adding
>>> an element at a particular position results in greater latency than
>>> appending or prefixing an element to a list.
>>>
>>>
>>> Best regards, Vladimir Yudovin,
>>>
>>> *Winguzone <https://winguzone.com?from=list> - Hosted Cloud
>>> CassandraLaunch your cluster in minutes.*
>>>
>>>
>>> ---- On Sat, 12 Nov 2016 07:57:36 -0500*Ali Akhtar
>>> <ali.rac200@gmail.com <ali.rac200@gmail.com>>* wrote ----
>>>
>>> The labels collection is of the type set<frozen<label>> , where label
is
>>> a udt containing: id, name, description , all text fields.
>>>
>>> On Sat, Nov 12, 2016 at 5:54 PM, Ali Akhtar <ali.rac200@gmail.com>
>>> wrote:
>>>
>>> The problem isn't just the update / insert though, right? Don't frozen
>>> entities get overwritten completely? So if I had [1] [2] being written as
>>> updates, won't each update overwrite the set completely, so i'll end up
>>> with either one of them instead of [1,2]?
>>>
>>> On Sat, Nov 12, 2016 at 5:50 PM, DuyHai Doan <doanduyhai@gmail.com>
>>> wrote:
>>>
>>> Maybe you should use my Achilles mapper, which does generates UPDATE
>>> statements on collections and not only INSERT
>>> Le 12 nov. 2016 13:08, "Ali Akhtar" <ali.rac200@gmail.com> a écrit :
>>>
>>> I am using the Java Cassandra mapper for all of these cases, so my code
>>> looks like this:
>>>
>>> Item myItem = myaccessor.get( itemId );
>>> Mapper<Item> mapper = mappingManager.create( Item.class );
>>>
>>> myItem.labels.add( newLabel );
>>> mapper.save( myItem );
>>>
>>> On Sat, Nov 12, 2016 at 5:06 PM, Ali Akhtar <ali.rac200@gmail.com>
>>> wrote:
>>>
>>> Thanks DuyHai, I will switch to using a set.
>>>
>>> But I'm still not sure how to resolve the original question.
>>>
>>> - Original labels = []
>>> - Request 1 arrives with label = 1, and request 2 arrives with label = 2
>>> - Updates are sent to c* with labels = [1] and labels = [2]
>>> simultaneously.
>>>
>>> What will happen in the above case? Will it cause the labels to end up
>>> as [1,2] (what I want) or either [1] or [2]?
>>>
>>> If I use consistency level = all, will that cause it to end up with
>>> [1,2]?
>>>
>>> On Sat, Nov 12, 2016 at 4:59 PM, DuyHai Doan <doanduyhai@gmail.com>
>>> wrote:
>>>
>>> Don't use list, use set instead. If you need ordering of insertion, use
>>> a map<timeuuid,text> where timeuuid is generated by the client to guarantee
>>> insertion order
>>>
>>> When setting a new value to a list, C* will do a read-delete-write
>>> internally e.g. read the current list, remove all its value (by a range
>>> tombstone) and then write the new list. Please note that prepend & append
>>> operations on list do not require this read-delete-write and thus performs
>>> slightly better
>>>
>>> On Sat, Nov 12, 2016 at 11:34 AM, Ali Akhtar <ali.rac200@gmail.com>
>>> wrote:
>>>
>>> I have a table where each record contains a list<string> of labels.
>>>
>>> I have an endpoint which responds to new labels being added to a record
>>> by the user.
>>>
>>> Consider the following scenario:
>>>
>>> - Record X, labels = []
>>> - User selects 2 labels, clicks a button, and 2 http requests are
>>> generated.
>>> - The server receives request for Label 1 and Label 2 at the same time.
>>> - Both requests see the labels as empty, add 1 label to the collection,
>>> and send it.
>>> - Record state as label 1 request sees it: [1], as label 2 sees it: [2]
>>>
>>> How will the above conflict be resolved? What can I do so I end up with
>>> [1, 2] instead of either [1] or [2] after both requests have been processed?
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>

Mime
View raw message