希望你能更多地了解非NoSQL的Redis
大家都喜欢Redis,真的很好。我也经常使用它。
在中国,Redis通常被用作NoSQL键值存储库或缓存存储。然而,只有那些开发高访问量网站并且对性能要求较高的工程师才需要这样的使用方式。
いや、Redisはもっとできる子なんです。今回の記事では小規模な開発でも、キーバリューストアやキャッシュ用途以外の使い道があるよということをまとめてみました。
1. 作为消息队列使用
我认为在多个进程之间使用消息队列进行值传递是可能的。
如果使用RDB。
如果使用关系数据库(RDB)。
-
- 插入数值
-
- 获取数值
- 删除读取的数值
借助Redis的一种类型——列表类型,很容易实现消息队列。
首先,在消息投入方面,我们将从列表的开头开始逐步添加消息。
LPUSH MyQueue "MessageA" => MyQueueは["MessageA"]
LPUSH MyQueue "MessageB" => MyQueueは["MessageB","MessageA"]
如果使用Spring Data Redis,上述的Redis命令将变成这样。
@Autowired
private RedisTemplate redisTemplate;
public void lpush() {
redisTemplate.opsForList().leftPush("MyQueue", "MessageA");
redisTemplate.opsForList().leftPush("MyQueue", "MessageB");
}
关于在Spring Boot中使用Redis的设置,请参考Java:Spring Boot で Redis を使う!- akihyrox。
在消息获取端,我们将从列表的末尾开始添加消息。
RPOP MyQueue ==> MessageAが返される
RPOP MyQueue ==> MessageBが返される
如果使用SpringDataRedis,上述的Redis命令将会如下所示。
@Autowired
private RedisTemplate redisTemplate;
public void lpush() {
String v;
v = redisTemplate.opsForList().rightPop("MyQueue");
v = redisTemplate.opsForList().rightPop("MyQueue");
}
通过Redis的消息传递,可以在不同进程之间进行方法调用和参数交换等消息交流,可将其作为消息队列使用。
我认为在实际运用中,使用RPOPLPUSH将正在执行的消息转移到另一个列表(执行中列表),然后在执行结束时从执行中列表中删除的实现方式是不错的。
参考
Redis文档日语翻译 数据类型-列表类型
2. 用作摇滚音乐中的乐器
在处理通过Web请求注册数据的情况下,需要进行某种形式的锁定以防止重复注册。有时会在RDB上创建锁定表并进行锁定标志的检查,但是如果解锁失败,锁定表上的标志可能会残留下来,这会带来一些风险。
另一个用于在 Redis 中实现简单锁定机制的命令。
-
- キーが存在していない場合には値をセットしてその返り値として 1 を返します。
- キーが既にあった場合は、値をセットしないでその返り値として 0 を返します。
SETNX MyLockKey "Locked" ==> 返り値は 1
SETNX MyLockKey "Locked2" ==> 返り値は 0 MyLockKeyの値は "Locked"のまま
通过查看此返回值,您可以确定是否被锁定。
此外,在Redis中,您可以为注册的键设置过期时间(Expire)。一旦过期,Redis会自动删除该键,因此即使在删除键的操作失败的情况下,您也可以无需进行操作来解锁。
使用SETNX指令的示例中,可以如下指定EXPIRE。在这个示例中,为键MyLockKey设置了60秒的有效期。
SETNX MyLockKey "Locked"
EXPIRE MyLockKey 60
使用SpringDataRedis时,锁定处理将如下所示。
@Autowired
private RedisTemplate redisTemplate;
public void process() {
while (true) {
// ロックがかかっていないで、値が登録できた場合はisLock = true
// すでに値が登録されていた場合はisLock = false
Boolean isLock = redisTemplate.opsForValue().setIfAbsent("MyLockKey", "Locked");
// 60秒のExpireを設定
redisTemplate.expire("MyLockKey", 60, TimeUnit.Seconds);
if (isLock) {
// ロック取得した後の処理
// ここで上のメッセージキューを読みだして処理を行うとかできます。
.....
// 正常終了した後のロック解除
redisTemplate.delete("MyLockKey");
} else {
// ロック中
}
}
}
参考
在Redis的日本文档翻译中,关于数据类型-字符串类型有相关的内容。
使用Redis的setnx功能可以在多服务器环境下实现Web API的锁机制。这篇文章发布在Developers.IO上。
3. 用于消息传递的发布/订阅机制
在希望通过除了HTTP请求以外的触发器来执行某些操作的情况下,使用发布/订阅的消息传递机制可以在任意时间执行处理。
Redis已经内建了这样的机制,因此可以轻松地实现消息传递。
使用PUBLISH来发送消息,使用SUBSCRIBE来订阅。
执行SUBSCRIBE命令后,将等待指定频道作为参数执行PUBLISH操作。
SUBSCRIBE MyMessage
我要在当前状态下从另一个进程对这个通道进行PUBLISH操作。
PUBLISH MyMessage "Send Message"
随后,订阅方便接收到消息,并持续等待直到下一条消息到达。
SpringDataRedisを用いたPub/Sub実装は少し長くなるので、こちらのサイトを参照してみてください。
PubSub Messaging with Spring Data Redis -baeldung
参考:redis文件日文翻译 中文文档 发布/订阅
顺便说一下
http://www.baeldung.com には、SpringBootを用いた実装例が簡潔に多く掲載されており非常に参考になります。
https://www.baeldung.com/category/spring/ 上的与Spring相关的索引