I just learnt about Redis and Redisson as well. Basically I am trying to use Redis for storing AcessTokens/RefreshTokens used for authorization in my app. So I want to store the tokens with an expiration time. I used Spring Data Redis to store the token but there is no Api to expire each entry in a Map. I came across this post Spring Data Redis Expire Key and hence looked up Redisson. I tried a simple maven java project to test the expiration. Here is pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bridgelabz</groupId>
<artifactId>redissonApp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>redissonApp</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
</project>
Below is Token class
package com.bridgelabz.redissonApp;
public class Token {
private String accessToken;
private int id;
public Token() { }
public Token(String accessToken, int id) {
this.accessToken = accessToken;
this.id = id;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Token [accessToken=" + accessToken + ", id=" + id + "]";
}
}
And here is my demo App:
package com.bridgelabz.redissonApp;
import java.util.concurrent.TimeUnit;
import org.redisson.Redisson;
import org.redisson.api.LocalCachedMapOptions;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.redisson.api.LocalCachedMapOptions.EvictionPolicy;
import org.redisson.config.Config;
public class App {
public static void main(String[] args) {
Config config = new Config();
config.useSingleServer().setAddress("127.0.0.1:6379");
// LocalCachedMapOptions localCachedMapOptions =
// LocalCachedMapOptions.defaults()
// .evictionPolicy(EvictionPolicy.LFU);
RedissonClient redisson = Redisson.create(config);
try {
RMapCache<Integer, Token> map = redisson.getMapCache("TestMap");
Token myToken = new Token("abc", 1);
map.put(1, myToken, 10, TimeUnit.SECONDS);
System.out.println("Stored value with key 1 is: " + map.get(1));
}
finally {
redisson.shutdown();
}
}
}
After running App.java I get the output I get the output as:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Stored value with key 1 is: Token [accessToken=abc, id=1]
And just commenting the put code and running the app after 10 seconds gives me the partly desired result:
LF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Stored value with key 1 is: null
But when I run redis-cli I'm still getting the value in the output:
127.0.0.1:6379> hget TestMap 1
"\x00\x00\x00\x00\x00\x00\x00\x00H\x00\x00\x00\x00\x00\x00\x00{\"@class\":\"com.bridgelabz.redissonApp.Token\",\"accessToken\":\"abc\",\"id\":1}"
Why isn't the key removed from redis also? FYI: Everything is being tested on my local machine only including redis.
I don't know the reasoning but the key's expired when I used the same code in Spring Web App but didn't work in a simple Java Application. Here is code for TokenDaoImpl.java:
Previously, when running Java App, I had two Maps in redis- one which I created i.e.
TokenMap
and and new map which hasMapName_session_timeout
and the keys would remain even after the specified expiration. Now all keys are removed correctly.Redis does not support individual element eviction out of the box for hashes. So Redisson has built its own solution and named it
MapCache
.So with
MapCache
, you now have two levels expiry control: Key level which offered by Redis, and field level which offered by Redisson.In your test code:
You have set the expiry on the field
1
of the hashTestMap
. That means the hash does not have an expiry set against it, rather that an expiry is set against one of the field it has. So when you look it up in usingredis-cli
, the hash still exists. It eventually will disappear when the Redisson expiration process kicks in.