Slim3 シャーディングカウンタを改良した!
Slim3 シャーディングカウンタ作ってみた。 - SinDiary
先日作成したシャーディングカウンタですが、あおうさ殿にご指南をいただきました!
修正したのはServiceでQueryを使っていたところです。
Queryではなく、Getを用いて取得するようにしました。
それに伴いKeyの生成方法も変更しています。
Google Code Archive - Long-term storage for Google Code Project Hosting.
@Model(schemaVersion = 1)
public class CounterShard implements Serializable {private static final long serialVersionUID = 1L;
private static final int startKeyNumber = 1;
....
public static Key createKey(CounterShardType name) {
Random random = new Random();
int number = random.nextInt(name.getNumShards()) + startKeyNumber;
return createKey(name, number);
}public static Key createKey(CounterShardType name, int number) {
String id = String.format("%s%d", name, number);
return Datastore.createKey(CounterShard.class, id);
}public static List
getKeyList(CounterShardType name) {
Listkeys = new ArrayList ();
for (int i = 0; i < name.getNumShards(); i++) {
keys.add(createKey(name, i + startKeyNumber));
}
return keys;
}
}
Google Code Archive - Long-term storage for Google Code Project Hosting.
import java.util.Map;import org.slim3.datastore.Datastore;
import org.slim3.memcache.Memcache;
import org.smallreunion.meta.CounterShardMeta;
import org.smallreunion.model.CounterShard;
import org.smallreunion.model.constract.CounterShardType;import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;public class CounterShardService {
CounterShardMeta meta = new CounterShardMeta();
public int getCount(CounterShardType name) {
if (Memcache.contains(name)) {
return Memcache.get(name);
}
int total = 0;
MapcounterShards =
Datastore.getAsMap(meta, CounterShard.getKeyList(name));
for (CounterShard counterShard : counterShards.values()) {
total += counterShard.getCount();
}
return total;
}public Key increment(CounterShardType name) {
Key key = CounterShard.createKey(name);Transaction tx = Datastore.beginTransaction();
try {
CounterShard counter = Datastore.getOrNull(meta, key);
if (counter == null) {
counter = CounterShard.getInstance(name);
counter.setKey(key);
}
counter.increment();
Key result = Datastore.put(counter);
tx.commit();
incrementMemcache(name);
return result;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
}protected void incrementMemcache(CounterShardType name) {
if (!Memcache.contains(name)) {
return;
}
Memcache.increment(name, 1);
}
}
ちょっと例外時の処理とかが、まだ適当だったり・・・。
あおうさ殿がBlogに書かれているソースの方が、しっかり作ってありますので、そちらも見た方が良いです!
というか、あおうさ殿のBlogの方だけ見れば良いんじゃないかなと思いますw