Hi Duy Hai,

On 04 Apr 2014, at 20:48, DuyHai Doan <doanduy...@gmail.com> wrote:

> @Jan
> 
>  Your use-case is different than what i though. So basically you have only 
> one data source (the feed) and many consumers (the workers)
> 
>  Only one worker is allowed to consumer the feed at a time.
> 
>  This can be modeled very easily using distributed lock with C.A.S

thank you - this confirms a design I am using in a similar scenario. However, I 
have problems there when concurrency is getting high - maybe my C* version is a 
too-early version 2. But since you confirm the design, I’ll dig deeper into the 
issue. Also, I’ll try to spread out the workers using modulo calculations 
somehow.

Having said that - my impression was that what you suggest is sort of 'brute 
force coordination’ and that there is likely a more clever design - like your 
queuing example. That is why I went to the list for answers.

Thank you either way!

Jan



> 
> CREATE TABLE feed_lock (
>     lock text PRIMARY KEY,
>     worker_token text
> ); 
> 
> 1) First initialize the table with : INSERT INTO feed_lock (lock) 
> VALUES('lock'). The primary key value is hard-coded and is always the same: 
> 'lock'. It does not really matter. At this step, the column worker_token is 
> null since we did not insert any value in it
> 
> 2) If a worker w1 wants to get the lock: UPDATE feed_lock SET 
> worker_token='token1' WHERE lock='lock' IF worker_token=null.
> w1 tries to acquire the lock if it is not hold by any other worker (IF 
> worker_token=null)
> 
> 3) Concurrently, if another worker w2 tries to acquire the lock, it will fail 
> since worker_token is not null any more. 
> 
> 4) w1 will release the lock with: UPDATE feed_lock SET worker_token=null 
> WHERE lock='lock' IF worker_token='token1'
> The important detail here is that only w1 knows the value of token1 so only 
> w1 is able to release the lock
> 
> This is a very simple design.
> 
>  Now it can happen that the lock is never released because one worker holding 
> it crashed and the secret token is lost. To circumvent that, you can held the 
> lock using an update with TTL. The lock will be released no matter how after 
> the TTL expires. If the processing of the feed takes longer than the TTL 
> time, the current worker can always extends the lease with another update 
> with TTL again to reset the TTL value.
> 
>  Hope that helps
> 
>  Regards
> 
>  Duy Hai DOAN
> 
> 
> 
>   
> 
> 
> On Fri, Apr 4, 2014 at 6:48 PM, Jan Algermissen <jan.algermis...@nordsc.com> 
> wrote:
> Hi DuyHai,
> 
> 
> On 04 Apr 2014, at 13:58, DuyHai Doan <doanduy...@gmail.com> wrote:
> 
> > @Jan
> >
> >  This subject of distributed workers & queues has been discussed in the 
> > mailing list many times.
> 
> Sorry + thanks.
> 
> Unfortunately, I do not want to use C* as a queue, but to coordinate workers 
> that page through an (XML) data feed of events every N seconds.
> 
> Let me try again:
> 
> - I have N instances of the same system, replicated to ensure work is
>   being done despite failure of instances
> - the instances are master less and know nothing about each other. Given
>   them an integer ID isn’r really possible and the number of instances isn’t
>   really known
> - there is a schedule, controlling how often the feed is read, say once every 
> Minute
> - the schedule might change by way of an administrator of the ‘feed polling’
> - the worker instances check for work every, e.g. 10 secs
> - once a worker starts, it checks whether there is work to do (the schedule 
> aspect) and if so,
>   starts polling the feed until the last event has been reached.
> - During that time, no other worker must poll the feed
> - once the working worker is done it saves the timestamp or ID of the last 
> seen event and sets the next schedule
> 
> - the processing of the events might take much longer than the schedule 
> intervals
> 
> I hope this explains more, what I am up to. Maybe I can adapt your 
> suggestion, I just do not see how.
> 
> Jan
> 
> 
> 
> > Basically one implementation can be:
> >
> > 1) p data providers, c data consumers
> > 2) create partitions (physical rows) of arbitrary number of columns (let's 
> > say 10 000, not too big though). Partition key = bucket number (#b)
> > 3) assign an integer id (pId) to each provider, same for each consumer (cId)
> > 4) each provider can only write messages in bucket number such that #b mod 
> > p = pId mod p
> > 5) once the provider reaches 10 000 messages per bucket, it switches to the 
> > next one with new #b = old #b + p
> > 6) the consumers follow the same rule for bucket switching
> >
> > Example:
> >
> >  p = 5, c = 3
> >
> >  - p1 writes messages into buckets {1,6,11,16...} // 1, 1+5, 1+5+5, ....
> >  - p2 writes messages into buckets {2,7,12,17...} // 2, 2+5, 2+5+5,...
> >  - p3 writes messages into buckets {3,8,13,18...}
> >  - p4 writes messages into buckets {4,9,14,19...}
> >  - p5 writes messages into buckets {5,10,15,20...}
> >
> >  - c1 consumes messages from buckets {1,4,7,10...} // 1, 1+3, 1+3+3...
> >  - c2 consumes messages from buckets {2,5,8,11...}
> >  - c1 consumes messages from buckets {3,6,9,12...}
> >
> > Of course, consumers can not re-put messages into the bucket otherwise the 
> > counting (10 000 elements/bucket) is screwed
> >
> > Alternatively, you can insert messages with TTL to automatically expired 
> > "consumed buckets" after a while, saving you the hassle to clean up old 
> > buckets to reclaim disk space.
> >
> >
> >  There are other implementations based on distributed lock using C* C.A.S 
> > also but the above algorithm do not requires any lock.
> >
> > Regards
> >
> >  Duy Hai DOAN
> >
> >
> >
> >
> >
> > On Fri, Apr 4, 2014 at 12:47 PM, prem yadav <ipremya...@gmail.com> wrote:
> > Oh ok. I thought you did not have a cassandra cluster already. Sorry about 
> > that.
> >
> >
> > On Fri, Apr 4, 2014 at 11:42 AM, Jan Algermissen 
> > <jan.algermis...@nordsc.com> wrote:
> >
> > On 04 Apr 2014, at 11:18, prem yadav <ipremya...@gmail.com> wrote:
> >
> >> Though cassandra can work but to me it looks like you could use a 
> >> persistent queue for example (rabbitMQ) to implement this. All your 
> >> workers can subscribe to a queue.
> >> In fact, why not just MySQL?
> >
> > Hey, I have got a C* cluster that can (potentially) do CAS.
> >
> > Why would I set up a MySQL cluster to solve that problem?
> >
> > And yeah, I could use a queue or redis or whatnot, but I want to avoid yet 
> > another moving part :-)
> >
> > Jan
> >
> >
> >>
> >>
> >> On Thu, Apr 3, 2014 at 11:44 PM, Jan Algermissen 
> >> <jan.algermis...@nordsc.com> wrote:
> >> Hi,
> >>
> >> maybe someone knows a nice solution to the following problem:
> >>
> >> I have N worker processes that are intentionally masterless and do not 
> >> know about each other - they are stateless and independent instances of a 
> >> given service system.
> >>
> >> These workers need to poll an event feed, say about every 10 seconds and 
> >> persist a state after processing the polled events so the next worker 
> >> knows where to continue processing events.
> >>
> >> I would like to use C*’s CAS feature to coordinate the workers and protect 
> >> the shared state (a row or cell in  a C* key space, too).
> >>
> >> Has anybody done something similar and can suggest a ‘clever’ data model 
> >> design and interaction?
> >>
> >>
> >>
> >> Jan
> >>
> >
> >
> >
> 
> 

Reply via email to