BAEL-3613: Reading All Available Redis Keys (#8490)

This commit is contained in:
Tapan Avasthi 2020-01-23 22:00:12 +05:30 committed by Sam Millington
parent f46ea65783
commit 6bca22524a
10 changed files with 537 additions and 1 deletions

View File

@ -38,7 +38,7 @@
</dependencies>
<properties>
<jedis.version>2.9.0</jedis.version>
<jedis.version>3.2.0</jedis.version>
<embedded-redis.version>0.6</embedded-redis.version>
<redisson.version>3.3.0</redisson.version>
<lettuce-core.version>5.0.1.RELEASE</lettuce-core.version>

View File

@ -0,0 +1,149 @@
package com.baeldung.redis_scan.client;
import com.baeldung.redis_scan.iterator.RedisIterator;
import com.baeldung.redis_scan.strategy.ScanStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
public class RedisClient {
private static Logger log = LoggerFactory.getLogger(RedisClient.class);
private static volatile RedisClient instance = null;
private static JedisPool jedisPool;
public static RedisClient getInstance(String ip, final int port) {
if (instance == null) {
synchronized (RedisClient.class) {
if (instance == null) {
instance = new RedisClient(ip, port);
}
}
}
return instance;
}
private RedisClient(String ip, int port) {
try {
if (jedisPool == null) {
jedisPool = new JedisPool(new URI("http://" + ip + ":" + port));
}
} catch (URISyntaxException e) {
log.error("Malformed server address", e);
}
}
public Long lpush(final String key, final String[] strings) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.lpush(key, strings);
} catch (Exception ex) {
log.error("Exception caught in lpush", ex);
}
return null;
}
public List<String> lrange(final String key, final long start, final long stop) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.lrange(key, start, stop);
} catch (Exception ex) {
log.error("Exception caught in lrange", ex);
}
return new LinkedList<String>();
}
public String hmset(final String key, final Map<String, String> hash) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.hmset(key, hash);
} catch (Exception ex) {
log.error("Exception caught in hmset", ex);
}
return null;
}
public Map<String, String> hgetAll(final String key) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.hgetAll(key);
} catch (Exception ex) {
log.error("Exception caught in hgetAll", ex);
}
return new HashMap<String, String>();
}
public Long sadd(final String key, final String... members) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.sadd(key, members);
} catch (Exception ex) {
log.error("Exception caught in sadd", ex);
}
return null;
}
public Set<String> smembers(final String key) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.smembers(key);
} catch (Exception ex) {
log.error("Exception caught in smembers", ex);
}
return new HashSet<String>();
}
public Long zadd(final String key, final Map<String, Double> scoreMembers) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.zadd(key, scoreMembers);
} catch (Exception ex) {
log.error("Exception caught in zadd", ex);
}
return 0L;
}
public Set<String> zrange(final String key, final long start, final long stop) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.zrange(key, start, stop);
} catch (Exception ex) {
log.error("Exception caught in zrange", ex);
}
return new HashSet<String>();
}
public String mset(final HashMap<String, String> keysValues) {
try (Jedis jedis = jedisPool.getResource()) {
ArrayList<String> keysValuesArrayList = new ArrayList<String>();
keysValues.forEach((key, value) -> {
keysValuesArrayList.add(key);
keysValuesArrayList.add(value);
});
return jedis.mset((keysValuesArrayList.toArray(new String[keysValues.size()])));
} catch (Exception ex) {
log.error("Exception caught in mset", ex);
}
return null;
}
public Set<String> keys(final String pattern) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.keys(pattern);
} catch (Exception ex) {
log.error("Exception caught in keys", ex);
}
return new HashSet<String>();
}
public RedisIterator iterator(int initialScanCount, String pattern, ScanStrategy strategy) {
return new RedisIterator(jedisPool, initialScanCount, pattern, strategy);
}
public void flushAll() {
try (Jedis jedis = jedisPool.getResource()) {
jedis.flushAll();
} catch (Exception ex) {
log.error("Exception caught in flushAll", ex);
}
}
}

View File

@ -0,0 +1,60 @@
package com.baeldung.redis_scan.iterator;
import com.baeldung.redis_scan.strategy.ScanStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class RedisIterator<T> implements Iterator<List<T>> {
private static Logger log = LoggerFactory.getLogger(RedisIterator.class);
private static final int DEFAULT_SCAN_COUNT = 10;
private final JedisPool jedisPool;
private ScanParams scanParams;
private String cursor;
private ScanStrategy<T> strategy;
public RedisIterator(JedisPool jedisPool, int initialScanCount, String pattern, ScanStrategy<T> strategy) {
super();
this.jedisPool = jedisPool;
this.scanParams = new ScanParams().match(pattern).count(initialScanCount);
this.strategy = strategy;
}
public RedisIterator(JedisPool jedisPool, String pattern, ScanStrategy<T> strategy) {
super();
this.jedisPool = jedisPool;
this.scanParams = new ScanParams().match(pattern).count(DEFAULT_SCAN_COUNT);
this.strategy = strategy;
}
@Override
public boolean hasNext() {
return !"0".equals(cursor);
}
@Override
public List<T> next() {
if (cursor == null) {
cursor = "0";
}
try (Jedis jedis = jedisPool.getResource()) {
ScanResult<T> scanResult = strategy.scan(jedis, cursor, scanParams);
cursor = scanResult.getCursor();
return scanResult.getResult();
} catch (Exception ex) {
log.error("Exception caught in next()", ex);
}
return new LinkedList<T>();
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.redis_scan.strategy;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
public interface ScanStrategy<T> {
ScanResult<T> scan(Jedis jedis, String cursor, ScanParams scanParams);
}

View File

@ -0,0 +1,25 @@
package com.baeldung.redis_scan.strategy.impl;
import com.baeldung.redis_scan.strategy.ScanStrategy;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import java.util.Map;
import java.util.Map.Entry;
public class Hscan implements ScanStrategy<Map.Entry<String, String>> {
private String key;
public Hscan(String key) {
super();
this.key = key;
}
@Override
public ScanResult<Entry<String, String>> scan(Jedis jedis, String cursor, ScanParams scanParams) {
return jedis.hscan(key, cursor, scanParams);
}
}

View File

@ -0,0 +1,14 @@
package com.baeldung.redis_scan.strategy.impl;
import com.baeldung.redis_scan.strategy.ScanStrategy;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
public class Scan implements ScanStrategy<String> {
public ScanResult<String> scan(Jedis jedis, String cursor, ScanParams scanParams) {
return jedis.scan(cursor, scanParams);
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.redis_scan.strategy.impl;
import com.baeldung.redis_scan.strategy.ScanStrategy;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
public class Sscan implements ScanStrategy<String> {
private String key;
public Sscan(String key) {
super();
this.key = key;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public ScanResult<String> scan(Jedis jedis, String cursor, ScanParams scanParams) {
return jedis.sscan(key, cursor, scanParams);
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.redis_scan.strategy.impl;
import com.baeldung.redis_scan.strategy.ScanStrategy;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import redis.clients.jedis.Tuple;
public class Zscan implements ScanStrategy<Tuple> {
private String key;
public Zscan(String key) {
super();
this.key = key;
}
@Override
public ScanResult<Tuple> scan(Jedis jedis, String cursor, ScanParams scanParams) {
return jedis.zscan(key, cursor, scanParams);
}
}

View File

@ -0,0 +1,96 @@
package com.baeldung.redis_scan;
import com.baeldung.redis_scan.client.RedisClient;
import org.junit.*;
import redis.embedded.RedisServer;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class NaiveApproachIntegrationTest {
private static RedisServer redisServer;
private static int port;
private static RedisClient redisClient;
@BeforeClass
public static void setUp() throws IOException {
// Take an available port
ServerSocket s = new ServerSocket(0);
port = s.getLocalPort();
s.close();
redisServer = new RedisServer(port);
redisServer.start();
}
@AfterClass
public static void destroy() {
if (redisServer.isActive())
redisServer.stop();
}
@Before
public void init() {
if (!redisServer.isActive()) {
redisServer.start();
}
redisClient = RedisClient.getInstance("127.0.0.1", port);
}
@After
public void flushAll() {
redisClient.flushAll();
}
@Test
public void testKeys() {
HashMap<String, String> keyValues = new HashMap<String, String>();
keyValues.put("balls:cricket", "160");
keyValues.put("balls:football", "450");
keyValues.put("balls:volleyball", "270");
redisClient.mset(keyValues);
Set<String> readKeys = redisClient.keys("ball*");
Assert.assertEquals(keyValues.size(), readKeys.size());
}
@Test
public void testSmembers() {
HashSet<String> setMembers = new HashSet<String>();
setMembers.add("cricket_160");
setMembers.add("football_450");
setMembers.add("volleyball_270");
redisClient.sadd("balls", setMembers.toArray(new String[setMembers.size()]));
Set<String> readSetMembers = redisClient.smembers("balls");
Assert.assertEquals(setMembers.size(), readSetMembers.size());
}
@Test
public void testHgetAll() {
HashMap<String, String> keyValues = new HashMap<String, String>();
keyValues.put("balls:cricket", "160");
keyValues.put("balls:football", "450");
keyValues.put("balls:volleyball", "270");
redisClient.hmset("balls", keyValues);
Map<String, String> readHash = redisClient.hgetAll("balls");
Assert.assertEquals(keyValues.size(), readHash.size());
}
@Test
public void testZRange() {
HashMap<String, Double> scoreMembers = new HashMap<String, Double>();
scoreMembers.put("cricket", (double) 160);
scoreMembers.put("football", (double) 450);
scoreMembers.put("volleyball", (double) 270);
redisClient.zadd("balls", scoreMembers);
Set<String> readSetMembers = redisClient.zrange("balls", 0, -1);
Assert.assertEquals(readSetMembers.size(), scoreMembers.size());
}
}

View File

@ -0,0 +1,129 @@
package com.baeldung.redis_scan;
import com.baeldung.redis_scan.client.RedisClient;
import com.baeldung.redis_scan.iterator.RedisIterator;
import com.baeldung.redis_scan.strategy.ScanStrategy;
import com.baeldung.redis_scan.strategy.impl.Hscan;
import com.baeldung.redis_scan.strategy.impl.Scan;
import com.baeldung.redis_scan.strategy.impl.Sscan;
import com.baeldung.redis_scan.strategy.impl.Zscan;
import org.junit.*;
import redis.clients.jedis.Tuple;
import redis.embedded.RedisServer;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.*;
public class ScanStrategyIntegrationTest {
private static RedisServer redisServer;
private static int port;
private static RedisClient redisClient;
@BeforeClass
public static void setUp() throws IOException {
// Take an available port
ServerSocket s = new ServerSocket(0);
String ip = "127.0.0.1";
port = s.getLocalPort();
s.close();
redisServer = new RedisServer(port);
redisServer.start();
}
@AfterClass
public static void destroy() {
if (redisServer.isActive())
redisServer.stop();
}
@Before
public void init() {
if (!redisServer.isActive()) {
redisServer.start();
}
redisClient = RedisClient.getInstance("127.0.0.1", port);
}
@After
public void flushAll() {
redisClient.flushAll();
}
@Test
public void testScanStrategy() {
HashMap<String, String> keyValues = new HashMap<String, String>();
keyValues.put("balls:cricket", "160");
keyValues.put("balls:football", "450");
keyValues.put("balls:volleyball", "270");
redisClient.mset(keyValues);
ScanStrategy<String> scanStrategy = new Scan();
int iterationCount = 2;
RedisIterator iterator = redisClient.iterator(iterationCount, "ball*", scanStrategy);
List<String> results = new LinkedList<String>();
while (iterator.hasNext()) {
results.addAll(iterator.next());
}
Assert.assertEquals(keyValues.size(), results.size());
}
@Test
public void testSscanStrategy() {
HashSet<String> setMembers = new HashSet<String>();
setMembers.add("cricket_160");
setMembers.add("football_450");
setMembers.add("volleyball_270");
redisClient.sadd("balls", setMembers.toArray(new String[setMembers.size()]));
Sscan scanStrategy = new Sscan("balls");
int iterationCount = 2;
RedisIterator iterator = redisClient.iterator(iterationCount, "*", scanStrategy);
List<String> results = new LinkedList<String>();
while (iterator.hasNext()) {
results.addAll(iterator.next());
}
Assert.assertEquals(setMembers.size(), results.size());
}
@Test
public void testHscanStrategy() {
HashMap<String, String> hash = new HashMap<String, String>();
hash.put("cricket", "160");
hash.put("football", "450");
hash.put("volleyball", "270");
redisClient.hmset("balls", hash);
Hscan scanStrategy = new Hscan("balls");
int iterationCount = 2;
RedisIterator iterator = redisClient.iterator(iterationCount, "*", scanStrategy);
List<Map.Entry<String, String>> results = new LinkedList<Map.Entry<String, String>>();
while (iterator.hasNext()) {
results.addAll(iterator.next());
}
Assert.assertEquals(hash.size(), results.size());
}
@Test
public void testZscanStrategy() {
HashMap<String, Double> memberScores = new HashMap<String, Double>();
memberScores.put("cricket", (double) 160);
memberScores.put("football", (double) 450);
memberScores.put("volleyball", (double) 270);
redisClient.zadd("balls", memberScores);
Zscan scanStrategy = new Zscan("balls");
int iterationCount = 2;
RedisIterator iterator = redisClient.iterator(iterationCount, "*", scanStrategy);
List<Tuple> results = new LinkedList<Tuple>();
while (iterator.hasNext()) {
results.addAll(iterator.next());
}
Assert.assertEquals(memberScores.size(), results.size());
}
}