java Jedis 和 Lettuce 异步能力
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32857922/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Jedis and Lettuce async abilities
提问by cykopath
I am using redis with Akka so I need no blocking calls. Lettuce has async-future call built into it. But Jedis is the recommended client by Redis. Can someone tell me if I am using both of them the right way. If so which one is better.
我在 Akka 中使用 redis,所以我不需要阻塞调用。Lettuce 内置了异步未来调用。但是 Jedis 是 Redis 推荐的客户端。有人可以告诉我是否以正确的方式使用它们。如果是,哪个更好。
JEDISI am using a static Jedis connection pool to get con and using Akka future callback to process the result. My concern here is when I use another thread (callable) to get the result that thread is eventually going to block for the result. While Lettuce might have some more efficient way of doing this.
JEDIS我使用静态 Jedis 连接池来获取 con 并使用 Akka 未来回调来处理结果。我在这里担心的是,当我使用另一个线程(可调用)来获得线程最终会阻塞的结果时。虽然生菜可能有一些更有效的方法来做到这一点。
private final class OnSuccessExtension extends OnSuccess<String> {
private final ActorRef senderActorRef;
private final Object message;
@Override
public void onSuccess(String valueRedis) throws Throwable {
log.info(getContext().dispatcher().toString());
senderActorRef.tell((String) message, ActorRef.noSender());
}
public OnSuccessExtension(ActorRef senderActorRef,Object message) {
this.senderActorRef = senderActorRef;
this.message=message;
}
}
ActorRef senderActorRef = getSender(); //never close over a future
if (message instanceof String) {
Future<String> f =akka.dispatch.Futures.future(new Callable<String>() {
public String call() {
String result;
try(Jedis jedis=JedisWrapper.redisPool.getResource()) {
result = jedis.get("name");
}
return result;
}
}, ex);
f.onSuccess(new OnSuccessExtension(senderActorRef,message), ex);
}
LETTUCE
莴苣
ExecutorService executorService = Executors.newFixedThreadPool(10);
public void onReceive(Object message) throws Exception {
ActorRef senderActorRef = getSender(); //never close over a future
if (message instanceof String) {
final RedisFuture<String> future = lettuce.connection.get("name");
future.addListener(new Runnable() {
final ActorRef sender = senderActorRef;
final String msg =(String) message;
@Override
public void run() {
try {
String value = future.get();
log.info(value);
sender.tell(message, ActorRef.noSender());
} catch (Exception e) {
}
}
}, executorService);
If lettuce is a better option for Async calls. Then what type of executor should I go with in production environment. If possible can I use a Akka dispatcher as an execution context for Letture future call.
如果生菜是异步调用的更好选择。那么我应该在生产环境中使用什么类型的执行器。如果可能,我可以使用 Akka 调度程序作为 Letture 未来调用的执行上下文。
回答by mp911de
There is no one answer to your question because it depends.
你的问题没有一个答案,因为这取决于。
Jedis and lettuce are both mature clients. To complete the list of Java clients, there is also Redisson, which adds another layer of abstraction (Collection/Queue/Lock/... interfaces instead of raw Redis commands).
Jedis 和 lettuce 都是成熟的客户。为了完成 Java 客户端列表,还有 Redisson,它添加了另一层抽象(Collection/Queue/Lock/... 接口而不是原始 Redis 命令)。
It pretty much depends on how you're working with the clients. In general, Redis is single-threaded in terms of data access, so the only benefit you gain by concurrency is offloading the protocol and I/O work to different threads. That is not fully true to lettuce and Redisson since they use netty under the hood (netty binds one socket channel to a particular event loop thread).
这在很大程度上取决于您如何与客户合作。一般而言,Redis 在数据访问方面是单线程的,因此通过并发获得的唯一好处是将协议和 I/O 工作卸载到不同的线程。这对生菜和 Redisson 来说并不完全正确,因为它们在幕后使用 netty(netty 将一个套接字通道绑定到特定的事件循环线程)。
With Jedis, you can use only one connection only with one thread at a time. That correlates nicely with the Akka actor model because one actor instance is occupied only by one thread at a time.
使用 Jedis,您一次只能通过一个线程使用一个连接。这与 Akka actor 模型非常相关,因为一个 actor 实例一次仅被一个线程占用。
On the other side, you need as much Jedis connections as threads that deal with a particular actor. If you start sharing Jedis connections across different actors, you either go for connection pooling, or you need to have a dedicated Jedis connection per actor instance. Please keep in mind that you need to take care of the reconnection (once a Redis connection is broken) by yourself.
另一方面,您需要与处理特定参与者的线程一样多的 Jedis 连接。如果您开始在不同的 actor 之间共享 Jedis 连接,您要么使用连接池,要么需要每个 actor 实例都有一个专用的 Jedis 连接。请记住,您需要自己处理重新连接(一旦 Redis 连接中断)。
With Redisson and lettuce, you get transparent reconnection if you wish to do so (That's the default value to lettuce, not sure about Redisson).
使用 Redisson 和生菜,如果您愿意,您可以获得透明的重新连接(这是生菜的默认值,不确定 Redisson)。
By using lettuce and Redisson you can share one connection amongst all actors because they are thread-safe. You cannot share one lettuce connection in two cases:
通过使用生菜和 Redisson,您可以在所有参与者之间共享一个连接,因为它们是线程安全的。在两种情况下,您不能共享一个生菜连接:
- Blocking operations (since you would block all other users of the connection)
- Transactions (
MULTI
/EXEC
, since you would mix different operations with the transactions and that is certainly a thing you do not want to do so)
- 阻塞操作(因为您会阻塞连接的所有其他用户)
- 交易(
MULTI
/EXEC
,因为您会将不同的操作与交易混合使用,这当然是您不想这样做的事情)
Jedis has no async interface, so you're required to do this by yourself. That's feasible, and I did something similar with MongoDB, offloading/decoupling the I/O part to other actors. You can use the approach from your code, but you're not required to provide an own executor service because you do non-blocking operations in the runnable listener.
Jedis 没有异步接口,因此您需要自己完成此操作。这是可行的,我对 MongoDB 做了类似的事情,将 I/O 部分卸载/解耦到其他参与者。您可以使用代码中的方法,但不需要提供自己的执行程序服务,因为您在可运行侦听器中执行非阻塞操作。
With lettuce 4.0 you'll get Java 8 support (which is way better in terms of the async API because of the CompletionStage interface), and you can even use RxJava (reactive programming) to approach concurrency.
使用生菜 4.0,您将获得 Java 8 支持(由于 CompletionStage 接口,这在异步 API 方面更好),您甚至可以使用 RxJava(反应式编程)来处理并发。
Lettuce is not opinionated on your concurrency model. It allows you to use it according to you needs, except the plain Future
/ListenableFuture
API of Java 6/7 and Guava is not very nice to use.
Lettuce 对您的并发模型没有偏见。它允许您根据需要使用它,除了Java 6/7和Guava的普通Future
/ ListenableFuture
API不是很好用。
HTH, Mark
HTH,马克
回答by Nikita Koksharov
Give a try to Redissonframework. It provides Asynchronous API as well as Reactive Streams API supported through integration with Project Reactor and RxJava2 libs.
尝试Redisson框架。它通过与 Project Reactor 和 RxJava2 库的集成提供异步 API 以及响应式流 API。
Asynchronous API usage example:
异步 API 使用示例:
RedissonClient client = Redisson.create(config);
RMap<String, String> map = client.getMap("myMap");
// implements CompletionStage interface
RFuture<String> future = map.get("myKey");
future.whenComplete((res, exception) -> {
// ...
});
Reactive Streams API with Project Reactor lib usage example:
带有 Project Reactor 库的 Reactive Streams API 使用示例:
RedissonReactiveClient client = Redisson.createReactive(config);
RMapReactive<String, String> map = client.getMap("myMap");
Mono<String> resp = map.get("myKey");
Reactive Streams API with RxJava2 lib usage example:
带有 RxJava2 库的 Reactive Streams API 使用示例:
RedissonRxClient client = Redisson.createRx(config);
RMapRx<String, String> map = client.getMap("myMap");
Flowable<String> resp = map.get("myKey");