Skip to content

Instantly share code, notes, and snippets.

@pangda0xff
Created July 24, 2018 09:25
Show Gist options
  • Save pangda0xff/a012daa3713a865b1f55a2b03e196971 to your computer and use it in GitHub Desktop.
Save pangda0xff/a012daa3713a865b1f55a2b03e196971 to your computer and use it in GitHub Desktop.
A Cache implement using redis and kryo
package com.keruyun.ca.selection.site.cache;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.pool.KryoPool;
import org.springframework.cache.Cache;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.util.concurrent.Callable;
/**
* A redis cache using kryo and prefix
*/
public class RedisCache implements Cache {
private static final int KEY_BUFFER_SIZE = 200;
private static final int VALUE_BUFFER_SIZE = 3000;
private JedisPool jedisPool;
private KryoPool kryoPool;
private String name;
private int duration;
public RedisCache(JedisPool jedisPool, KryoPool kryoPool, String name, int duration) {
this.jedisPool = jedisPool;
this.kryoPool = kryoPool;
this.name = name;
this.duration = duration;
}
@Override
public String getName() {
return name;
}
@Override
public Object getNativeCache() {
return jedisPool;
}
@Override
public ValueWrapper get(Object key) {
Kryo kryo = kryoPool.borrow();
try {
Output output = new Output(KEY_BUFFER_SIZE);
kryo.writeObject(output, name + key);
byte[] value;
try (Jedis jedis = jedisPool.getResource()) {
value = jedis.get(output.toBytes());
}
if (value == null) {
return null;
} else {
return () -> value;
}
} finally {
kryoPool.release(kryo);
}
}
@Override
public <T> T get(Object key, Class<T> type) {
Kryo kryo = kryoPool.borrow();
try {
Output output = new Output(KEY_BUFFER_SIZE);
kryo.writeObject(output, name + key);
byte[] value;
try (Jedis jedis = jedisPool.getResource()) {
value = jedis.get(output.toBytes());
}
return value == null ? null : kryo.readObject(new Input(value), type);
} finally {
kryoPool.release(kryo);
}
}
@Override
public <T> T get(Object key, Callable<T> valueLoader) {
ValueWrapper valueWrapper = get(key);
if (valueLoader != null) {
return (T) valueWrapper.get();
}
try {
T ret = valueLoader.call();
put(key, ret);
return ret;
} catch (Exception e) {
throw new ValueRetrievalException(key, valueLoader, e);
}
}
@Override
public void put(Object key, Object value) {
Kryo kryo = kryoPool.borrow();
try {
Output keyOutput = new Output(KEY_BUFFER_SIZE);
kryo.writeObject(keyOutput, name + key);
Output valueOutput = new Output(VALUE_BUFFER_SIZE);
kryo.writeObject(valueOutput, value);
try (Jedis jedis = jedisPool.getResource()) {
jedis.setex(keyOutput.toBytes(), duration, valueOutput.toBytes());
}
} finally {
kryoPool.release(kryo);
}
}
@Override
public ValueWrapper putIfAbsent(Object key, Object value) {
ValueWrapper ret = get(key);
if (ret != null) {
return ret;
}
Kryo kryo = kryoPool.borrow();
try {
Output keyOutput = new Output(KEY_BUFFER_SIZE);
kryo.writeObject(keyOutput, name + key);
Output valueOutput = new Output(VALUE_BUFFER_SIZE);
kryo.writeObject(valueOutput, value);
try (Jedis jedis = jedisPool.getResource()) {
byte[] keybytes = keyOutput.toBytes();
long effect = jedis.setnx(keybytes, valueOutput.toBytes());
if (effect > 0) {
jedis.expire(keybytes, duration);
}
}
} finally {
kryoPool.release(kryo);
}
return null;
}
@Override
public void evict(Object key) {
Kryo kryo = kryoPool.borrow();
try {
Output keyOutput = new Output(KEY_BUFFER_SIZE);
kryo.writeObject(keyOutput, name + key);
try (Jedis jedis = jedisPool.getResource()) {
jedis.del(name + key);
}
} finally {
kryoPool.release(kryo);
}
}
@Override
public void clear() {
// not support
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment