Skip to content

Commit

Permalink
#1 - Update to Ebean 11.38.1 with better metrics collection and repor…
Browse files Browse the repository at this point in the history
…ting
  • Loading branch information
rbygrave committed May 3, 2019
1 parent cfb64de commit 0f7eda2
Show file tree
Hide file tree
Showing 12 changed files with 414 additions and 231 deletions.
23 changes: 19 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>io.ebean</groupId>
<artifactId>ebean-redis</artifactId>
<version>11.31.2-SNAPSHOT</version>
<version>11.38.1-SNAPSHOT</version>

<parent>
<groupId>org.avaje</groupId>
Expand All @@ -28,14 +28,29 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>11.31.1</version>
<version>11.38.1</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>11.38.1</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>11.38.1</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.ebean.test</groupId>
<artifactId>ebean-test-config</artifactId>
<version>11.29.1</version>
<version>11.38.1</version>
<scope>test</scope>
</dependency>

<dependency>
Expand Down Expand Up @@ -64,7 +79,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:7.2</tile>
<tile>io.ebean.tile:enhancement:11.38.1</tile>
</tiles>
</configuration>
</plugin>
Expand Down
80 changes: 40 additions & 40 deletions src/main/java/io/ebean/redis/DuelCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,33 @@

import io.ebean.cache.ServerCache;
import io.ebean.cache.ServerCacheStatistics;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.server.cache.DefaultServerCache;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.LongAdder;

public class DuelCache implements ServerCache, NearCacheInvalidate {

private final ServerCache near;
private final ServerCache remote;
private final DefaultServerCache near;
private final RedisCache remote;
private final NearCacheNotify cacheNotify;
private final String cacheKey;

private final LongAdder nearMissCount = new LongAdder();
private final LongAdder nearHitCount = new LongAdder();
private final LongAdder remoteMissCount = new LongAdder();
private final LongAdder remoteHitCount = new LongAdder();

public DuelCache(ServerCache near, ServerCache remote, String cacheKey, NearCacheNotify cacheNotify) {
public DuelCache(DefaultServerCache near, RedisCache remote, String cacheKey, NearCacheNotify cacheNotify) {
this.near = near;
this.remote = remote;
this.cacheKey = cacheKey;
this.cacheNotify = cacheNotify;
}

@Override
public void visit(MetricVisitor visitor) {
near.visit(visitor);
remote.visit(visitor);
}

@Override
public void invalidateKeys(Set<Object> keySet) {
near.removeAll(keySet);
Expand All @@ -46,10 +48,6 @@ public void invalidateClear() {
public Map<Object, Object> getAll(Set<Object> keys) {

Map<Object, Object> resultMap = near.getAll(keys);

nearHitCount.add(resultMap.size());
nearMissCount.add(keys.size() - resultMap.size());

Set<Object> localKeys = resultMap.keySet();

Set<Object> remainingKeys = new HashSet<>();
Expand All @@ -61,10 +59,6 @@ public Map<Object, Object> getAll(Set<Object> keys) {
if (!remainingKeys.isEmpty()) {
// fetch missing ones from remote cache and merge results
Map<Object, Object> remoteMap = remote.getAll(remainingKeys);

remoteHitCount.add(remoteMap.size());
remoteMissCount.add(remainingKeys.size() - remoteMap.size());

if (!remoteMap.isEmpty()) {
near.putAll(remoteMap);
resultMap.putAll(remoteMap);
Expand All @@ -78,15 +72,10 @@ public Map<Object, Object> getAll(Set<Object> keys) {
public Object get(Object id) {
Object val = near.get(id);
if (val != null) {
nearHitCount.increment();
return val;
}
nearMissCount.increment();
Object remoteVal = remote.get(id);
if (remoteVal == null) {
remoteMissCount.increment();
} else {
remoteHitCount.increment();
if (remoteVal != null) {
near.put(id, remoteVal);
}
return remoteVal;
Expand All @@ -108,7 +97,6 @@ public void put(Object id, Object value) {

@Override
public void removeAll(Set<Object> keys) {

near.removeAll(keys);
remote.removeAll(keys);
cacheNotify.invalidateKeys(cacheKey, keys);
Expand All @@ -128,6 +116,34 @@ public void clear() {
cacheNotify.invalidateClear(cacheKey);
}

/**
* Return the near cache hit count.
*/
public long getNearHitCount() {
return near.getHitCount();
}

/**
* Return the near cache miss count.
*/
public long getNearMissCount() {
return near.getMissCount();
}

/**
* Return the redis cache hit count.
*/
public long getRemoteHitCount() {
return remote.getHitCount();
}

/**
* Return the redis cache miss count.
*/
public long getRemoteMissCount() {
return remote.getMissCount();
}

@Override
public int size() {
return 0;
Expand All @@ -142,20 +158,4 @@ public int getHitRatio() {
public ServerCacheStatistics getStatistics(boolean reset) {
return null;
}

public long getNearMissCount() {
return nearMissCount.longValue();
}

public long getNearHitCount() {
return nearHitCount.longValue();
}

public long getRemoteMissCount() {
return remoteMissCount.longValue();
}

public long getRemoteHitCount() {
return remoteHitCount.longValue();
}
}
105 changes: 88 additions & 17 deletions src/main/java/io/ebean/redis/RedisCache.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package io.ebean.redis;

import io.ebean.cache.ServerCache;
import io.ebean.cache.ServerCacheConfig;
import io.ebean.cache.ServerCacheStatistics;
import io.ebean.meta.MetricType;
import io.ebean.meta.MetricVisitor;
import io.ebean.metric.CountMetric;
import io.ebean.metric.MetricFactory;
import io.ebean.metric.TimedMetric;
import io.ebean.redis.encode.Encode;
import io.ebean.redis.encode.EncodePrefixKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.ScanParams;
Expand All @@ -19,8 +25,12 @@
import java.util.Map;
import java.util.Set;

import static io.ebean.meta.MetricType.L2;

class RedisCache implements ServerCache {

private static final Logger log = LoggerFactory.getLogger(RedisCache.class);

private static final String CURSOR_0 = "0";
private static final byte[] CURSOR_0_BYTES = SafeEncoder.encode(CURSOR_0);

Expand All @@ -36,24 +46,42 @@ class RedisCache implements ServerCache {
private final TimedMetric metricRemove;
private final TimedMetric metricRemoveAll;
private final TimedMetric metricClear;
private final CountMetric hitCount;
private final CountMetric missCount;

RedisCache(JedisPool jedisPool, ServerCacheConfig config, Encode valueEncode) {

RedisCache(JedisPool jedisPool, String cacheKey, Encode keyEncode, Encode valueEncode) {
this.jedisPool = jedisPool;
this.cacheKey = cacheKey;
this.keyEncode = keyEncode;
this.cacheKey = config.getCacheKey();
this.keyEncode = new EncodePrefixKey(config.getCacheKey());
this.valueEncode = valueEncode;

String prefix = "ebean.l2cache.";

MetricFactory metricFactory = MetricFactory.get();
String pre = "l2r.";
String shortName = config.getShortName();
MetricFactory factory = MetricFactory.get();

hitCount = factory.createCountMetric(L2, pre + shortName + ".hit");
missCount = factory.createCountMetric(L2, pre + shortName + ".miss");
metricGet = factory.createTimedMetric(MetricType.L2, pre + shortName + ".get");
metricGetAll = factory.createTimedMetric(MetricType.L2, pre + shortName + ".getMany");
metricPut = factory.createTimedMetric(MetricType.L2, pre + shortName + ".put");
metricPutAll = factory.createTimedMetric(MetricType.L2, pre + shortName + ".putMany");
metricRemove = factory.createTimedMetric(MetricType.L2, pre + shortName + ".remove");
metricRemoveAll = factory.createTimedMetric(MetricType.L2, pre + shortName + ".removeMany");
metricClear = factory.createTimedMetric(MetricType.L2, pre + shortName + ".clear");
}

metricGet = metricFactory.createTimedMetric(MetricType.L2, prefix + "get." + cacheKey);
metricGetAll = metricFactory.createTimedMetric(MetricType.L2, prefix + "getMany." + cacheKey);
metricPut = metricFactory.createTimedMetric(MetricType.L2, prefix + "put." + cacheKey);
metricPutAll = metricFactory.createTimedMetric(MetricType.L2, prefix + "putMany." + cacheKey);
metricRemove = metricFactory.createTimedMetric(MetricType.L2, prefix + "remove." + cacheKey);
metricRemoveAll = metricFactory.createTimedMetric(MetricType.L2, prefix + "removeMany." + cacheKey);
metricClear = metricFactory.createTimedMetric(MetricType.L2, prefix + "clear." + cacheKey);
@Override
public void visit(MetricVisitor visitor) {
hitCount.visit(visitor);
missCount.visit(visitor);
metricGet.visit(visitor);
metricGetAll.visit(visitor);
metricPut.visit(visitor);
metricPutAll.visit(visitor);
metricRemove.visit(visitor);
metricRemoveAll.visit(visitor);
metricClear.visit(visitor);
}

private byte[] key(Object id) {
Expand All @@ -68,10 +96,15 @@ private byte[] value(Object data) {
}

private Object valueDecode(byte[] data) {
if (data == null) {
try {
if (data == null) {
return null;
}
return valueEncode.decode(data);
} catch (Exception e) {
log.error("Error decoding data, treated as cache miss", e);
return null;
}
return valueEncode.decode(data);
}

@Override
Expand All @@ -84,7 +117,18 @@ public Map<Object, Object> getAll(Set<Object> keys) {
try (Jedis resource = jedisPool.getResource()) {
List<byte[]> valsAsBytes = resource.mget(keysAsBytes(keyList));
for (int i = 0; i < keyList.size(); i++) {
map.put(keyList.get(i), valueDecode(valsAsBytes.get(i)));
Object val = valueDecode(valsAsBytes.get(i));
if (val != null) {
map.put(keyList.get(i), val);
}
}
int hits = map.size();
int miss = keys.size() - hits;
if (hits > 0) {
hitCount.add(hits);
}
if (miss > 0) {
missCount.add(miss);
}
metricGetAll.addSinceNanos(start, keyList.size());
return map;
Expand All @@ -96,6 +140,11 @@ public Object get(Object id) {
long start = System.nanoTime();
try (Jedis resource = jedisPool.getResource()) {
Object val = valueDecode(resource.get(key(id)));
if (val != null) {
hitCount.increment();
} else {
missCount.increment();
}
metricGet.addSinceNanos(start);
return val;
}
Expand Down Expand Up @@ -183,6 +232,20 @@ public void clear() {
}
}

/**
* Return the count of get hits.
*/
public long getHitCount() {
return hitCount.get(false);
}

/**
* Return the count of get misses.
*/
public long getMissCount() {
return missCount.get(false);
}

@Override
public int size() {
return 0;
Expand All @@ -195,6 +258,14 @@ public int getHitRatio() {

@Override
public ServerCacheStatistics getStatistics(boolean reset) {
return null;

ServerCacheStatistics cacheStats = new ServerCacheStatistics();
cacheStats.setCacheName(cacheKey);
cacheStats.setHitCount(hitCount.get(reset));
cacheStats.setMissCount(missCount.get(reset));
cacheStats.setPutCount(metricPut.collect(reset).getCount());
cacheStats.setRemoveCount(metricRemove.collect(reset).getCount());
cacheStats.setClearCount(metricClear.collect(reset).getCount());
return cacheStats;
}
}
Loading

0 comments on commit 0f7eda2

Please sign in to comment.