foreword
Redis added the Stream function after 5.0. Redis is used more in daily projects, but the Stream function is used less. Today, I learned the basic functions of Stream, which can facilitate the encounter in the next project. to the appropriate scene to use.
interface code
public interface IStreamServer {
/**
* 添加消息
* @param key
* @param streamEntryID
* @param content
* @return
*/
StreamEntryID xadd(String key, StreamEntryID streamEntryID, Map<String, String> content);
/**
* 创建分组
* @param stream
* @param group
* @param makeStream
* @return
*/
String xgroupCreate(String stream, String group, Boolean makeStream);
/**
* 倒序获取历史消息
* @param key
* @param end
* @param start
* @param count
* @return
*/
List<StreamEntry> xrevrange(String key, StreamEntryID end, StreamEntryID start, int count);
/**
* 正序获取历史消息
* @param key
* @param start
* @param end
* @param count
* @return
*/
List<StreamEntry> xrange(String key, StreamEntryID start, StreamEntryID end, int count);
/**
* 按分组获取消息
* @param group
* @param consumer
* @param count
* @param streams
* @return
*/
List<Map.Entry<String, List<StreamEntry>>> xreadGroup(String group, String consumer, int count, Map.Entry<String, StreamEntryID>... streams);
/**
* 获取消息
* @param count 获取数据
* @param streams 起始消息ID
* @return
*/
List<Map.Entry<String, List<StreamEntry>>> xread(int count, Map.Entry<String, StreamEntryID>... streams);
}
Implement class code
public class StreamServiceImpl implements IStreamServer {
@Resource
private Pool<Jedis> jedisPool;
@Override
public StreamEntryID xadd(String key, StreamEntryID streamEntryID, Map<String, String> content) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.xadd(key, streamEntryID, content);
}
}
@Override
public String xgroupCreate(String stream, String group, Boolean makeStream) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.xgroupCreate(stream, group, null, makeStream);
}
}
@Override
public List<StreamEntry> xrevrange(String key, StreamEntryID end, StreamEntryID start, int count) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.xrevrange(key, end, start, count);
}
}
@Override
public List<StreamEntry> xrange(String key, StreamEntryID start, StreamEntryID end, int count) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.xrange(key, start, end, count);
}
}
@Override
public List<Map.Entry<String, List<StreamEntry>>> xreadGroup(String group, String consumer, int count, Map.Entry<String, StreamEntryID>... streams) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.xreadGroup(group, consumer, count, 0, false, streams);
}
}
@Override
public List<Map.Entry<String, List<StreamEntry>>> xread(int count, Map.Entry<String, StreamEntryID>... streams) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.xread(count, 0, streams);
}
}
}
test code
public class RedisStreamTest extends BaseTest {
@Resource
private IStreamServer iStreamServer;
@Test
public void setGroup() throws Exception {
//创建 流名为 video 分组为 group1
String res = iStreamServer.xgroupCreate("video", "group1", true);
//创建 流名为 audio分组为 group1
String res2 = iStreamServer.xgroupCreate("audio", "group1", true);
}
@Test
public void xadd() throws Exception {
Long time = System.currentTimeMillis();
//向audio中插入100条消息
for (int i = 0; i < 100; i++) {
StreamEntryID streamEntryID = new StreamEntryID(String.format("%s-%s", time, i));
StreamEntryID id = iStreamServer.xadd("audio", streamEntryID, ImmutableMap.of("id", String.valueOf(i)));
System.out.println(id);
}
//向video中插入100条消息
for (int i = 0; i < 100; i++) {
StreamEntryID streamEntryID = new StreamEntryID(String.format("%s-%s", time, i));
StreamEntryID id = iStreamServer.xadd("video", streamEntryID, ImmutableMap.of("id", String.valueOf(i)));
System.out.println(id);
}
}
@Test
public void xreadGroup() throws Exception {
Map<String, StreamEntryID> t = MapUtil.of("video", null);
Map<String, StreamEntryID> t2 = MapUtil.of("audio", null);
Map.Entry<String, StreamEntryID> video = t.entrySet().stream().findFirst().get();
Map.Entry<String, StreamEntryID> audio = t2.entrySet().stream().findFirst().get();
//client1 用 group1 分组 从 video/audio 流中获取两个消息 ,同一分组中不同客户端可共享消费消息(client1消费一条,client2消息偏移量增加1 ),不同分组中的客户端消息不影响(client1消费一条,不影响client2消息偏移量)
List<Map.Entry<String, List<StreamEntry>>> list = iStreamServer.xreadGroup("group1", "client1", 2, video, audio);
list.forEach(x -> {
System.out.println(x.getKey() + "-->" + x.getValue());
});
//输出
/**
video-->[1610607445337-2 {id=2}, 1610607445337-3 {id=3}]
audio-->[1610608368683-2 {id=2}, 1610608368683-3 {id=3}]
**/
}
@Test
public void xrange() throws Exception {
//video中按正序 从1610607445337-10 到1610607445337-20 中获取3条消息
List<StreamEntry> streamEntries = iStreamServer.xrange("video", new StreamEntryID("1610607445337-10"), new StreamEntryID("1610607445337-20"), 3);
streamEntries.forEach(x -> System.out.println(x));
//输出
/**
1610607445337-10 {id=10}
1610607445337-11 {id=11}
1610607445337-12 {id=12}
**/
}
@Test
public void xrevrange() throws Exception {
//video中按倒序 从1610607445337-80 到1610607445337-0 中获取3条消息
List<StreamEntry> streamEntries = iStreamServer.xrevrange("video", new StreamEntryID("1610607445337-80"), new StreamEntryID("1610607445337-0"), 3);
streamEntries.forEach(x -> System.out.println(x));
//输出
/**
1610607445337-80 {id=80}
1610607445337-79 {id=79}
1610607445337-78 {id=78}
**/
}
@Test
public void xread() throws Exception {
//从1610607445337-2 开始获取
Map<String, StreamEntryID> t = MapUtil.of("video", new StreamEntryID("1610607445337-2"));
Map<String, StreamEntryID> t2 = MapUtil.of("audio", null);
Map.Entry<String, StreamEntryID> video = t.entrySet().stream().findFirst().get();
Map.Entry<String, StreamEntryID> audio = t2.entrySet().stream().findFirst().get();
// 从video 1610607445337-2 开始,从audio 0开始获取 2条消息
List<Map.Entry<String, List<StreamEntry>>> list = iStreamServer.xread(2, video, audio);
list.forEach(x -> {
System.out.println(x.getKey() + "-->" + x.getValue());
});
//输出
/**
audio-->[1610608368683-0 {id=0}, 1610608368683-1 {id=1}]
video-->[1610607445337-3 {id=3}, 1610607445337-4 {id=4}]
**/
}
}
Summarize
1. Redis Stream messages support persistence, and historical message records can be obtained at will
2. Redis Stream supports client grouping, and clients in the same group can jointly consume messages in the stream