开发者

How to make counter in transaction? (Sharding counters)

开发者 https://www.devze.com 2023-03-28 20:43 出处:网络
I\'ve read this but still can\'t get it. I want to do is a book store. There are lots of book objects and each book has two counters.

I've read this but still can't get it. I want to do is a book store. There are lots of book objects and each book has two counters. One counter is to record the number of people like it. Another is to record the number of people hate it. Obviously, I need to make the counter incremented in transactions in case more than 5 people like or hate a book in the same time, right?

My questions are:

1. How to make book and the counter in the same entity group s开发者_Python百科o that I can use them in the same transactions.

2. How to implement a sharding counters? I don't understand why (here in the third example) we need to have ShardedCounter, Counter and GeneralCounterShard and how do I use them?

3. Could anyone give me an example? I'm using JDO.

Thanks for any advice!


Are you really afraid that more than 5 people update the counters of the same book in the same second? that would be the sign of a huge traffic on your app. If so, you'll probably have more important problems to solve than the fact the a counter might be off by one or two votes.

I would simply make the counters part of the Book entity:

public class Book {
    // ...
    private int numberOfLovers;
    private int numberOfHaters;
    // ...
}

Keep it simple, and change your design if and only if you have a problem.


We drive quite a heavy-loaded cache app on AppEngine / Python (i.e. more than 200,000 requests per day with spikes of up to 60 per second) and we have to count everything (e.g. request, bytes in, bytes out).

Your problem seems less extreme; but, the solution we found was also more simple than those you mentioned (and also that we have read): we store counters in Memcache and use its "incr()" function wherever needed.

As Memcache manages sharding transparently, you don't have to think about it.

Then, a cron request is fired each minute to get values, store them in the datastore and decrement counters by the retrieved value with a call to the Memcache "decr()" function.

In this fashion, increments happening between getting and decrementing are not lost and will be treated the next minute.

Of course Memcache outages are a concern, but they don't happen frequently.


Entity group is helpful if you need to update few elements in one transaction. For example decrement value from one entity counter and increment at another. And need to be sure that or both operations are made or none of them.

As you need just increment one value (or two values from same entity) you don't need any groups.

Just update your entity, in transaction. GAE transaction uses optimistic locking, that means following steps:

  1. You're getting current value from db (by Key for example)
  2. Set values for any fields
  3. Put updated entity

And, while saving entity into db, gae will check that this entity wasn't updated since your first read (see step 1). If it still same - it saves your new value. If it changed - it throws exception. That's all.

If you have exception - you can reload entity, and try to update again.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号