Skip to content

Commit a08e90a

Browse files
christophstroblodrotbohm
authored andcommitted
DATAREDIS-414 - Serialization now occurs after pooled connection was released.
Moved key serialization and value deserialization outside of callback so that pooled connections get released more quickly. Original pull request: spring-projects#153.
1 parent 7073502 commit a08e90a

File tree

1 file changed

+85
-37
lines changed

1 file changed

+85
-37
lines changed

src/main/java/org/springframework/data/redis/cache/RedisCache.java

Lines changed: 85 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,17 @@ public ValueWrapper get(Object key) {
101101
public RedisCacheElement get(final RedisCacheKey cacheKey) {
102102

103103
notNull(cacheKey, "CacheKey must not be null!");
104-
return (RedisCacheElement) redisOperations.execute(new AbstractRedisCacheCallback<RedisCacheElement>(
105-
new RedisCacheElement(cacheKey, null), cacheMetadata) {
106104

107-
@Override
108-
public RedisCacheElement doInRedis(RedisCacheElement element, RedisConnection connection)
109-
throws DataAccessException {
105+
byte[] bytes = (byte[]) redisOperations.execute(new AbstractRedisCacheCallback<byte[]>(new BinaryRedisCacheElement(
106+
new RedisCacheElement(cacheKey, null), cacheValueAccessor), cacheMetadata) {
110107

111-
byte[] bs = connection.get(element.getKeyBytes());
112-
Object value = redisOperations.getValueSerializer() != null ? redisOperations.getValueSerializer().deserialize(bs) : bs;
113-
return (bs == null ? null : new RedisCacheElement(element.getKey(), value));
108+
@Override
109+
public byte[] doInRedis(BinaryRedisCacheElement element, RedisConnection connection) throws DataAccessException {
110+
return connection.get(element.getKeyBytes());
114111
}
115112
});
113+
114+
return (bytes == null ? null : new RedisCacheElement(cacheKey, cacheValueAccessor.deserializeIfNecessary(bytes)));
116115
}
117116

118117
/*
@@ -137,7 +136,9 @@ public void put(final Object key, final Object value) {
137136
public void put(RedisCacheElement element) {
138137

139138
notNull(element, "Element must not be null!");
140-
redisOperations.execute(new RedisCachePutCallback(element, cacheValueAccessor, cacheMetadata));
139+
140+
redisOperations.execute(new RedisCachePutCallback(new BinaryRedisCacheElement(element, cacheValueAccessor),
141+
cacheMetadata));
141142
}
142143

143144
/*
@@ -147,7 +148,8 @@ public void put(RedisCacheElement element) {
147148
public ValueWrapper putIfAbsent(Object key, final Object value) {
148149

149150
return putIfAbsent(new RedisCacheElement(new RedisCacheKey(key).usePrefix(cacheMetadata.getKeyPrefix())
150-
.withKeySerializer(redisOperations.getKeySerializer()), value).expireAfter(cacheMetadata.getDefaultExpiration()));
151+
.withKeySerializer(redisOperations.getKeySerializer()), value)
152+
.expireAfter(cacheMetadata.getDefaultExpiration()));
151153
}
152154

153155
/**
@@ -161,7 +163,12 @@ public ValueWrapper putIfAbsent(Object key, final Object value) {
161163
public ValueWrapper putIfAbsent(RedisCacheElement element) {
162164

163165
notNull(element, "Element must not be null!");
164-
return toWrapper(redisOperations.execute(new RedisCachePutIfAbsentCallback(element, cacheValueAccessor, cacheMetadata)));
166+
167+
new RedisCachePutIfAbsentCallback(new BinaryRedisCacheElement(element, cacheValueAccessor), cacheMetadata);
168+
169+
return toWrapper(cacheValueAccessor.deserializeIfNecessary((byte[]) redisOperations
170+
.execute(new RedisCachePutIfAbsentCallback(new BinaryRedisCacheElement(element, cacheValueAccessor),
171+
cacheMetadata))));
165172
}
166173

167174
/*
@@ -180,7 +187,8 @@ public void evict(Object key) {
180187
public void evict(final RedisCacheElement element) {
181188

182189
notNull(element, "Element must not be null!");
183-
redisOperations.execute(new RedisCacheEvictCallback(element, cacheMetadata));
190+
redisOperations.execute(new RedisCacheEvictCallback(new BinaryRedisCacheElement(element, cacheValueAccessor),
191+
cacheMetadata));
184192
}
185193

186194
/*
@@ -323,6 +331,10 @@ static class CacheValueAccessor {
323331

324332
byte[] convertToBytesIfNecessary(Object value) {
325333

334+
if (value == null) {
335+
return new byte[0];
336+
}
337+
326338
if (valueSerializer == null && value instanceof byte[]) {
327339
return (byte[]) value;
328340
}
@@ -340,6 +352,52 @@ Object deserializeIfNecessary(byte[] value) {
340352
}
341353
}
342354

355+
/**
356+
* @author Christoph Strobl
357+
* @since 1.6
358+
*/
359+
static class BinaryRedisCacheElement extends RedisCacheElement {
360+
361+
private byte[] keyBytes;
362+
private byte[] valueBytes;
363+
private RedisCacheElement element;
364+
365+
public BinaryRedisCacheElement(RedisCacheElement element, CacheValueAccessor accessor) {
366+
367+
super(element.getKey(), element.get());
368+
this.element = element;
369+
this.keyBytes = element.getKeyBytes();
370+
this.valueBytes = accessor.convertToBytesIfNecessary(element.get());
371+
}
372+
373+
@Override
374+
public byte[] getKeyBytes() {
375+
return keyBytes;
376+
}
377+
378+
public long getTimeToLive() {
379+
return element.getTimeToLive();
380+
}
381+
382+
public boolean hasKeyPrefix() {
383+
return element.hasKeyPrefix();
384+
}
385+
386+
public boolean isEternal() {
387+
return element.isEternal();
388+
}
389+
390+
public RedisCacheElement expireAfter(long seconds) {
391+
return element.expireAfter(seconds);
392+
}
393+
394+
@Override
395+
public byte[] get() {
396+
return valueBytes;
397+
}
398+
399+
}
400+
343401
/**
344402
* @author Christoph Strobl
345403
* @since 1.5
@@ -348,10 +406,10 @@ Object deserializeIfNecessary(byte[] value) {
348406
static abstract class AbstractRedisCacheCallback<T> implements RedisCallback<T> {
349407

350408
private long WAIT_FOR_LOCK_TIMEOUT = 300;
351-
private final RedisCacheElement element;
409+
private final BinaryRedisCacheElement element;
352410
private final RedisCacheMetadata cacheMetadata;
353411

354-
public AbstractRedisCacheCallback(RedisCacheElement element, RedisCacheMetadata metadata) {
412+
public AbstractRedisCacheCallback(BinaryRedisCacheElement element, RedisCacheMetadata metadata) {
355413
this.element = element;
356414
this.cacheMetadata = metadata;
357415
}
@@ -366,7 +424,7 @@ public T doInRedis(RedisConnection connection) throws DataAccessException {
366424
return doInRedis(element, connection);
367425
}
368426

369-
public abstract T doInRedis(RedisCacheElement element, RedisConnection connection) throws DataAccessException;
427+
public abstract T doInRedis(BinaryRedisCacheElement element, RedisConnection connection) throws DataAccessException;
370428

371429
protected void processKeyExpiration(RedisCacheElement element, RedisConnection connection) {
372430
if (!element.isEternal()) {
@@ -526,7 +584,7 @@ public Void doInLock(RedisConnection connection) throws DataAccessException {
526584
*/
527585
static class RedisCacheEvictCallback extends AbstractRedisCacheCallback<Void> {
528586

529-
public RedisCacheEvictCallback(RedisCacheElement element, RedisCacheMetadata metadata) {
587+
public RedisCacheEvictCallback(BinaryRedisCacheElement element, RedisCacheMetadata metadata) {
530588
super(element, metadata);
531589
}
532590

@@ -535,7 +593,7 @@ public RedisCacheEvictCallback(RedisCacheElement element, RedisCacheMetadata met
535593
* @see org.springframework.data.redis.cache.RedisCache.AbstractRedisCacheCallback#doInRedis(org.springframework.data.redis.cache.RedisCacheElement, org.springframework.data.redis.connection.RedisConnection)
536594
*/
537595
@Override
538-
public Void doInRedis(RedisCacheElement element, RedisConnection connection) throws DataAccessException {
596+
public Void doInRedis(BinaryRedisCacheElement element, RedisConnection connection) throws DataAccessException {
539597

540598
connection.del(element.getKeyBytes());
541599
cleanKnownKeys(element, connection);
@@ -549,25 +607,21 @@ public Void doInRedis(RedisCacheElement element, RedisConnection connection) thr
549607
*/
550608
static class RedisCachePutCallback extends AbstractRedisCacheCallback<Void> {
551609

552-
private final CacheValueAccessor valueAccessor;
553-
554-
public RedisCachePutCallback(RedisCacheElement element, CacheValueAccessor valueAccessor,
555-
RedisCacheMetadata metadata) {
610+
public RedisCachePutCallback(BinaryRedisCacheElement element, RedisCacheMetadata metadata) {
556611

557612
super(element, metadata);
558-
this.valueAccessor = valueAccessor;
559613
}
560614

561615
/*
562616
* (non-Javadoc)
563617
* @see org.springframework.data.redis.cache.RedisCache.AbstractRedisPutCallback#doInRedis(org.springframework.data.redis.cache.RedisCache.RedisCacheElement, org.springframework.data.redis.connection.RedisConnection)
564618
*/
565619
@Override
566-
public Void doInRedis(RedisCacheElement element, RedisConnection connection) throws DataAccessException {
620+
public Void doInRedis(BinaryRedisCacheElement element, RedisConnection connection) throws DataAccessException {
567621

568622
connection.multi();
569623

570-
connection.set(element.getKeyBytes(), valueAccessor.convertToBytesIfNecessary(element.get()));
624+
connection.set(element.getKeyBytes(), element.get());
571625

572626
processKeyExpiration(element, connection);
573627
maintainKnownKeys(element, connection);
@@ -581,26 +635,21 @@ public Void doInRedis(RedisCacheElement element, RedisConnection connection) thr
581635
* @author Christoph Strobl
582636
* @since 1.5
583637
*/
584-
static class RedisCachePutIfAbsentCallback extends AbstractRedisCacheCallback<Object> {
585-
586-
private final CacheValueAccessor valueAccessor;
587-
588-
public RedisCachePutIfAbsentCallback(RedisCacheElement element, CacheValueAccessor valueAccessor,
589-
RedisCacheMetadata metadata) {
638+
static class RedisCachePutIfAbsentCallback extends AbstractRedisCacheCallback<byte[]> {
590639

640+
public RedisCachePutIfAbsentCallback(BinaryRedisCacheElement element, RedisCacheMetadata metadata) {
591641
super(element, metadata);
592-
this.valueAccessor = valueAccessor;
593642
}
594643

595644
/*
596645
* (non-Javadoc)
597646
* @see org.springframework.data.redis.cache.RedisCache.AbstractRedisPutCallback#doInRedis(org.springframework.data.redis.cache.RedisCache.RedisCacheElement, org.springframework.data.redis.connection.RedisConnection)
598647
*/
599648
@Override
600-
public Object doInRedis(RedisCacheElement element, RedisConnection connection) throws DataAccessException {
649+
public byte[] doInRedis(BinaryRedisCacheElement element, RedisConnection connection) throws DataAccessException {
601650

602651
waitForLock(connection);
603-
Object resultValue = put(element, connection);
652+
byte[] resultValue = put(element, connection);
604653

605654
if (nullSafeEquals(element.get(), resultValue)) {
606655
processKeyExpiration(element, connection);
@@ -610,11 +659,10 @@ public Object doInRedis(RedisCacheElement element, RedisConnection connection) t
610659
return resultValue;
611660
}
612661

613-
private Object put(RedisCacheElement element, RedisConnection connection) {
662+
private byte[] put(BinaryRedisCacheElement element, RedisConnection connection) {
614663

615-
boolean valueWasSet = connection.setNX(element.getKeyBytes(),
616-
valueAccessor.convertToBytesIfNecessary(element.get()));
617-
return valueWasSet ? null : valueAccessor.deserializeIfNecessary(connection.get(element.getKeyBytes()));
664+
boolean valueWasSet = connection.setNX(element.getKeyBytes(), element.get());
665+
return valueWasSet ? null : connection.get(element.getKeyBytes());
618666
}
619667
}
620668

0 commit comments

Comments
 (0)