Lettuce Asynchronous API

레디스 개발자 교육 신청 레디스 정기점검/기술지원
Redis Technical Support
레디스 엔터프라이즈 서버
Redis Enterprise Server

Lettuce Asynchronous API

이 가이드는 Lettuce 4.x에서 제공하는 비동기 API를 언제, 어떻게 사용하는지에 대한 설명입니다.
This guide will give you an impression how and when to use the asynchronous API provided by Lettuce 4.x.

1. 동기 부여 Motivation

비동기식 방법을 사용하면 네트워크 또는 디스크 I/O를 기다리는 스레드를 낭비하는 대신 더 나은 시스템 리소스를 활용할 수 있습니다. 대신 스레드를 완전히 활용하여 다른 작업을 수행할 수 있습니다. Lettuce는 다중 스레드 이벤트 기반 I/O 프레임워크인 netty 위에 클라이언트를 구축하여 비동기성을 촉진합니다. 모든 통신은 비동기적으로 처리됩니다. 기반이 동시(concurrently)에 명령을 처리할 수 있게 되면, 비동기성(asynchronicity)을 활용하는 것이 편리합니다. 차단(blocking) 및 동기 작업 소프트웨어를 동시 처리 시스템으로 전환하는 것은 훨씬 더 어렵습니다.
Asynchronous methodologies allow you to utilize better system resources, instead of wasting threads waiting for network or disk I/O. Threads can be fully utilized to perform other work instead. Lettuce facilitates asynchronicity from building the client on top of netty that is a multithreaded, event-driven I/O framework. All communication is handled asynchronously. Once the foundation is able to processes commands concurrently, it is convenient to take advantage from the asynchronicity. It is way harder to turn a blocking and synchronous working software into a concurrently processing system.

비동기성의 이해 Understanding Asynchronicity

비동기성은 전송이 완료되고 전송 응답이 처리되기 전에 다른 처리가 계속되도록 허용합니다. 이는 Lettuce, 특히 Redis의 맥락에서 이전 명령이 완료될 때까지 기다릴 필요 없이 여러 명령을 연속적으로 실행할 수 있음을 의미합니다. 이 작업 모드를 파이프라이닝이라고도 합니다. 다음 예는 작동 모드에 대한 인상을 줄 것입니다.
Asynchronicity permits other processing to continue before the transmission has finished and the response of the transmission is processed. This means, in the context of Lettuce and especially Redis, that multiple commands can be issued serially without the need of waiting to finish the preceding command. This mode of operation is also known as Pipelining. The following example should give you an impression of the mode of operation:

① Given client A and client B
② Client A triggers command SET A=B
③ Client B triggers at the same time of Client A command SET C=D
④ Redis receives command from Client A
⑤ Redis receives command from Client B
⑥ Redis processes SET A=B and responds OK to Client A
⑦ Client A receives the response and stores the response in the response handle
⑧ Redis processes SET C=D and responds OK to Client B
⑨ Client B receives the response and stores the response in the response handle

위 예의 두 클라이언트는 모두 응용 프로그램 내의 두 스레드 또는 연결이거나 물리적으로 분리된 두 클라이언트일 수 있습니다.
Both clients from the example above can be either two threads or connections within an application or two physically separated clients.

클라이언트는 별도의 프로세스, 스레드, 이벤트 루프, 액터, 파이버 등이 되어 서로 동시에 작동할 수 있습니다. Redis는 들어오는 명령을 직렬로 처리하고 대부분 단일 스레드로 작동합니다. 즉, 명령은 나중에 다루게 될 몇 가지 특징을 가지고 수신된 순서대로 처리됩니다.
Clients can operate concurrently to each other by either being separate processes, threads, event-loops, actors, fibers, etc. Redis processes incoming commands serially and operates mostly single-threaded. This means, commands are processed in the order they are received with some characteristic that we’ll cover later.

간단한 예를 들어 몇 가지 프로그램 흐름 세부 사항을 통해 향상시켜 보겠습니다.
Let’s take the simplified example and enhance it by some program flow details:

① Given client A
② Client A triggers command SET A=B
③ Client A uses the asynchronous API and can perform other processing
    클라이언트 A는 비동기 API를 사용하고 다른 처리를 수행할 수 있습니다.
④ Redis receives command from Client A
⑤ Redis processes SET A=B and responds OK to Client A
⑥ Client A receives the response and stores the response in the response handle
    클라이언트 A는 응답을 수신하고 응답 핸들에 응답을 저장합니다.
⑦ Client A can access now the response to its command without waiting (non-blocking)
    이제 클라이언트 A는 기다리지 않고 명령에 대한 응답에 액세스할 수 있습니다(비차단).

클라이언트 A는 명령 결과를 기다리지 않는 이점을 활용하여 계산 작업을 처리하거나 다른 Redis 명령을 실행할 수 있습니다. 클라이언트는 응답이 제공되는 즉시 명령 결과로 작업할 수 있습니다.
The Client A takes advantage from not waiting on the result of the command so it can process computational work or issue another Redis command. The client can work with the command result as soon as the response is available.

비동기성이 동기 API에 미치는 영향   Impact of asynchronicity to the synchronous API

이 가이드는 비동기 API를 이해하는 데 도움이 되지만 동기 API에 미치는 영향을 알아보는 것도 좋습니다. 동기 API의 일반적인 접근 방식은 비동기 API와 다르지 않습니다. 두 경우 모두 명령을 호출하고 Redis 서버로 전송하는 데 동일한 기능이 사용됩니다. 유일한 차이점은 동기 API를 사용하는 호출자의 차단 동작입니다. 차단은 명령 수준에서 발생하며 명령 완료 부분에만 영향을 미칩니다. 즉, 동기 API를 사용하는 여러 클라이언트가 서로를 차단하지 않고 동시에 동일한 연결에서 명령을 호출할 수 있음을 의미합니다. 동기 API에 대한 호출은 명령 응답이 처리되는 순간 차단 해제됩니다.
While this guide helps you to understand the asynchronous API it is worthwhile to learn the impact on the synchronous API. The general approach of the synchronous API is no different than the asynchronous API. In both cases, the same facilities are used to invoke and transport commands to the Redis server. The only difference is a blocking behavior of the caller that is using the synchronous API. Blocking happens on command level and affects only the command completion part, meaning multiple clients using the synchronous API can invoke commands on the same connection and at the same time without blocking each other. A call on the synchronous API is unblocked at the moment a command response was processed.

① Given client A and client B
② Client A triggers command SET A=B on the synchronous API and waits for the result
    클라이언트 A는 동기 API에서 SET A=B 명령을 트리거하고 결과를 기다립니다.
③ Client B triggers at the same time of Client A command SET C=D on the synchronous API and waits for the result
    클라이언트 B는 동기 API에서 클라이언트 A 명령 SET C=D와 동시에 트리거하고 결과를 기다립니다.
④ Redis receives command from Client A
⑤ Redis receives command from Client B
⑥ Redis processes SET A=B and responds OK to Client A
⑦ Client A receives the response and unblocks the program flow of Client A
    클라이언트 A는 응답을 받고 클라이언트 A의 프로그램 흐름 차단을 해제합니다.
⑧ Redis processes SET C=D and responds OK to Client B
⑨ Client B receives the response and unblocks the program flow of Client B
    클라이언트 B는 응답을 받고 클라이언트 B의 프로그램 흐름 차단을 해제합니다.

그러나 부작용을 피하기 위해 스레드 간에 연결을 공유해서는 안 되는 경우도 있습니다. 사례는 다음과 같습니다.
However, there are some cases you should not share a connection among threads to avoid side-effects. The cases are:

• Disabling flush-after-command to improve performance
    성능 향상을 위해 명령 후 플러시 비활성화
• The use of blocking operations like BLPOP. Blocking operations are queued on Redis until they can be executed. While one connection is blocked, other connections can issue commands to Redis. Once a command unblocks the blocking command (that said an LPUSH or RPUSH hits the list), the blocked connection is unblocked and can proceed after that.
    BLPOP과 같은 차단 작업을 사용합니다. 차단 작업은 실행될 수 있을 때까지 Redis의 대기열에 추가됩니다. 하나의 연결이 차단되는 동안 다른 연결은 Redis에 명령을 실행할 수 있습니다. 명령이 차단 명령(LPUSH 또는 RPUSH가 목록에 도달함)을 차단 해제하면 차단된 연결이 차단 해제되고 그 이후에 계속 진행할 수 있습니다.
• Transactions MULTI/EXEC
• Using multiple databases 여러 데이터베이스 사용

결과 처리 Result handles

비동기 API의 모든 명령 호출은 취소, 대기 및 구독(리스너)이 가능한 RedisFuture<T>를 생성합니다. CompleteableFuture<T> 또는 RedisFuture<T>는 값 계산이 아직 완료되지 않았기 때문에 처음에는 알 수 없는 결과에 대한 포인터입니다. RedisFuture<T>는 동기화 및 연결 작업을 제공합니다.
Every command invocation on the asynchronous API creates a RedisFuture<T> that can be canceled, awaited and subscribed (listener). A CompleteableFuture<T> or RedisFuture<T> is a pointer to the result that is initially unknown since the computation of its value is yet incomplete. A RedisFuture<T> provides operations for synchronization and chaining.

Example 6. First steps with CompletableFuture
The example prints the following lines:
이 예에서는 다음 줄을 인쇄합니다.
Current state: false
Current state: true
Got value: my value

리스너를 future에 연결하면 연결이 가능해집니다. 약속은 미래와 동의어로 사용될 수 있지만 모든 미래가 약속인 것은 아닙니다. Promise는 콜백/알림을 보장하므로 그 이름이 붙여졌습니다.
Attaching a listener to a future allows chaining. Promises can be used synonymous to futures, but not every future is a promise. A promise guarantees a callback/notification and thus it has come to its name.

future가 완료되면 호출되는 간단한 리스너:
A simple listener that gets called once the future completes:

Example 7. Using listeners with CompletableFuture 값 처리는 호출자에서 미래를 완성하는 사람이 호출하는 리스너로 이동합니다.
The value processing moves from the caller into a listener that is then called by whoever completes the future.
The example prints the following lines:
Current state: false
Got value: my value
Current state: true

위의 코드에서는 get() 메서드 호출로 인해 예외가 발생할 수 있으므로 예외 처리가 필요합니다. Future<T> 계산 중에 발생한 예외는 ExecutionException 내에서 전송됩니다. 발생할 수 있는 또 다른 예외는 InterruptedException입니다. 이는 get() 호출이 호출을 차단하고 차단된 스레드가 언제든지 중단될 수 있기 때문입니다. 시스템 종료를 생각해 보십시오.
The code from above requires exception handling since calls to the get() method can lead to exceptions. Exceptions raised during the computation of the Future<T> are transported within an ExecutionException. Another exception that may be thrown is the InterruptedException. This is because calls to get() are blocking calls and the blocked thread can be interrupted at any time. Just think about a system shutdown.

CompletionStage<T> 유형을 사용하면 Java 8부터 미래를 훨씬 더 정교하게 처리할 수 있습니다. CompletionStage<T>는 값 처리 체인을 소비, 변환 및 구축할 수 있습니다. 위의 코드는 Java 8에서 다음 스타일로 다시 작성할 수 있습니다.
The CompletionStage<T> type allows since Java 8 a much more sophisticated handling of futures. A CompletionStage<T> can consume, transform and build a chain of value processing. The code from above can be rewritten in Java 8 in the following style:

Example 8. Using a Consumer future listener
The example prints the following lines:
Current state: false
Got value: my value
Current state: true

Java 8 API 문서에서 CompletionStage<T> 유형에 대한 전체 참조를 찾을 수 있습니다.
You can find the full reference for the CompletionStage<T> type in the Java 8 API documentation.

2. 레터스를 사용하여 퓨처(미래, 선물先物) 만들기 Creating futures using Lettuce

레터스 퓨처는 초기 및 연결 작업에 사용될 수 있습니다.
Lettuce futures can be used for initial and chaining operations.

Lettuce future를 사용하면 non-blocking 동작을 볼 수 있습니다. 이는 모든 I/O 및 명령 처리가 netty EventLoop를 사용하여 비동기적으로 처리되기 때문입니다. Lettuce RedisFuture는 CompletionStage를 확장하므로(상속받으므로) 기본 유형의 모든 메서드를 사용할 수 있습니다.
When using Lettuce futures, you will notice the non-blocking behavior. This is because all I/O and command processing are handled asynchronously using the netty EventLoop. The Lettuce RedisFuture extends a CompletionStage so all methods of the base type are available.

Lettuce는 독립형, Sentinel, 게시/구독 및 클러스터 API에 퓨처를 공개합니다.
Lettuce exposes its futures on the Standalone, Sentinel, Publish/Subscribe and Cluster APIs.

Redis에 연결하는 것은 엄청나게 간단합니다.
Connecting to Redis is insanely simple:
다음 단계에서는 키에서 값을 얻으려면 GET 작업이 필요합니다.
In the next step, obtaining a value from a key requires the GET operation:

3. 선물(future) 소비하기 Consuming futures

선물(future)을 다룰 때 가장 먼저 하고 싶은 일은 선물을 소비하는 것입니다. 선물(future)을 소비한다는 것은 값을 얻는 것을 의미합니다. 다음은 호출 스레드를 차단하고 값을 인쇄하는 예입니다.
The first thing you want to do when working with futures is to consume them. Consuming a futures means obtaining the value. Here is an example that blocks the calling thread and prints the value:

Example 9. GET a key get() 메서드(풀 스타일)에 대한 호출은 적어도 값이 계산될 때까지 호출 스레드를 차단하지만 최악의 경우 무기한으로 차단합니다. 스레드를 소진시키지 않으려면 시간 초과를 사용하는 것이 항상 좋은 생각입니다.
Invocations to the get() method (pull-style) block the calling thread at least until the value is computed but in the worst case indefinitely. Using timeouts is always a good idea to not exhaust your threads.

Example 10. Blocking synchronization 이 예시는 future가 완료될 때까지 최대 1분을 기다립니다. 시간 초과가 초과되면 TimeoutException이 발생하여 시간 초과를 알립니다.
The example will wait at most 1 minute for the future to complete. If the timeout exceeds, a TimeoutException is thrown to signal the timeout.

Future는 푸시 스타일로 소비될 수도 있습니다. 즉, RedisFuture가 완료되면 후속 작업이 트리거됩니다.
Futures can also be consumed in a push style, meaning when the RedisFuture is completed, a follow-up action is triggered:

Example 11. Using a Consumer listener with GET 또는 Java 8 람다로 작성됩니다.
Alternatively, written in Java 8 lambdas:
Example 12. Using a Consumer lambda with GET
레터스 선물(future)은 netty EventLoop에서 완성됩니다. 기본 스레드에서 future를 사용하고 연결하는 것은 차단/장기 실행 작업이라는 한 가지 경우를 제외하고는 항상 좋은 생각입니다. 경험상 이벤트 루프를 차단하지 마십시오. 차단 호출을 사용하여 future를 연결해야 하는 경우 thenAcceptAsync()/thenRunAsync() 메서드를 사용하여 처리를 다른 스레드로 분기합니다. ...Async() 메서드는 실행을 위해 스레딩 인프라가 필요하며 기본적으로 ForkJoinPool.commonPool()이 사용됩니다. ForkJoinPool은 정적으로 구성되며 부하가 증가해도 증가하지 않습니다. 기본 실행자를 사용하는 것이 거의 항상 더 나은 아이디어입니다.
Lettuce futures are completed on the netty EventLoop. Consuming and chaining futures on the default thread is always a good idea except for one case: Blocking/long-running operations. As a rule of thumb, never block the event loop. If you need to chain futures using blocking calls, use the thenAcceptAsync()/thenRunAsync() methods to fork the processing to another thread. The …async() methods need a threading infrastructure for execution, by default the ForkJoinPool.commonPool() is used. The ForkJoinPool is statically constructed and does not grow with increasing load. Using default Executors is almost always the better idea.

Example 13. Asynchronous listener notification

4. 퓨처 동기화 Synchronizing futures

선물을 사용할 때 중요한 점은 동기화입니다. 선물은 일반적으로 다음과 같은 용도로 사용됩니다.
A key point when using futures is the synchronization. Futures are usually used to:

① 선행 작업을 기다리지 않고 여러 호출을 트리거합니다(일괄 처리).
    Trigger multiple invocations without the urge to wait for the predecessors (Batching)
② 결과를 전혀 기다리지 않고 명령 호출(Fire&Forget)
    Invoking a command without awaiting the result at all (Fire&Forget)
③ 명령을 호출하고 그 동안 다른 컴퓨팅을 수행함(디커플링)
    Invoking a command and perform other computing in the meantime (Decoupling)
④ 특정 계산 작업에 동시성 추가(동시성)
    Adding concurrency to certain computational efforts (Concurrency)

퓨처가 완료될 경우 기다리거나 알림을 받는 방법에는 여러 가지가 있습니다. 특정 동기화 기술은 선물을 사용하려는 몇 가지 동기에 적용됩니다.
There are several ways how to wait or get notified in case a future completes. Certain synchronization techniques apply to some motivations why you want to use futures.

동기화 차단 Blocking synchronization

시스템의 특정 부분에 일괄 처리/동시성을 추가하는 경우 동기화 차단이 편리합니다. 일괄 처리의 예로는 여러 값을 설정/검색하고 처리 내 특정 지점 이전에 결과를 기다리는 것이 있습니다.
Blocking synchronization comes handy if you perform batching/add concurrency to certain parts of your system. An example to batching can be setting/retrieving multiple values and awaiting the results before a certain point within processing.

Example 14. Getting multiple keys asynchronously 위의 코드는 특정 명령이 완료될 때까지 기다리지 않고 다른 명령을 실행합니다. 동기화는 모든 명령이 실행된 후에 수행됩니다. 예제 코드는 LettuceFutures.awaitAll() 호출을 생략하여 Fire&Forget 패턴으로 쉽게 전환할 수 있습니다.
The code from above does not wait until a certain command completes before it issues another one. The synchronization is done after all commands are issued. The example code can easily be turned into a Fire&Forget pattern by omitting the call to LettuceFutures.awaitAll().

단일 향후 실행도 기다릴 수 있습니다. 즉, 예외를 발생시키지 않고 특정 시간 동안 기다리도록 선택하는 것을 의미합니다.
A single future execution can be also awaited, meaning an opt-in to wait for a certain time but without raising an exception:
Example 15. Using RedisFuture.await to wait for a result 차단된 스레드가 중단된 경우에만 InterruptedException을 발생시키기 때문에 wait()를 호출하는 것이 더 호출하기 쉽습니다. 당신은 동기화를 위한 get() 메소드에 이미 익숙하므로 이 메소드에 대해 귀찮게 하지 않겠습니다.
Calling await() is friendlier to call since it throws only an InterruptedException in case the blocked thread is interrupted. You are already familiar with the get() method for synchronization, so we will not bother you with this one.

마지막으로, 차단 방식으로 퓨처를 동기화하는 또 다른 방법이 있습니다. 주요 주의 사항은 스레드 중단을 처리할 책임이 있다는 것입니다. 해당 측면을 처리하지 않으면 시스템이 실행 중인 상태에서 시스템을 제대로 종료할 수 없습니다.
At last, there is another way to synchronize futures in a blocking way. The major caveat is that you will become responsible to handle thread interruptions. If you do not handle that aspect, you will not be able to shut down your system properly if it is in a running state.
isDone() 메서드는 주로 동기화 사용을 목표로 하지 않지만 명령이 실행되는 동안 다른 계산 작업을 수행하는 것이 편리할 수 있습니다.
While the isDone() method does not aim primarily for synchronization use, it might come handy to perform other computational efforts while the command is executed.

체인 동기화 Chaining synchronization

스레드 활용도를 향상시키기 위해 Future를 비차단 스타일로 동기화/체인화할 수 있습니다. 체인화는 이벤트 중심 특성에 의존하는 시스템에서 매우 잘 작동합니다. 퓨처 체인은 순차적으로 실행되는 하나 이상의 퓨처 체인을 구축하며 모든 체인 구성원은 계산의 일부를 처리합니다. CompletionStage API는 퓨처를 연결하고 변환하는 다양한 방법을 제공합니다. thenApply() 메서드를 사용하여 값을 간단히 변환할 수 있습니다.
Futures can be synchronized/chained in a non-blocking style to improve thread utilization. Chaining works very well in systems relying on event-driven characteristics. Future chaining builds up a chain of one or more futures that are executed serially, and every chain member handles a part in the computation. The CompletionStage API offers various methods to chain and transform futures. A simple transformation of the value can be done using the thenApply() method:

Example 16. Future chaining Alternatively, written in Java 8 lambdas:
Example 17. Future chaining with lambdas thenApply() 메서드는 값을 다른 값으로 변환하는 함수를 허용합니다. 최종 thenAccept() 메서드는 최종 처리를 위해 값을 사용합니다.
The thenApply() method accepts a function that transforms the value into another one. The final thenAccept() method consumes the value for final processing.

----------------------------------------------------------------------
java.util.function.Function 설명

Java 8부터 도입된 함수형 인터페이스입니다.
이 인터페이스는 하나의 입력값을 받아서 다른 타입의 값을 반환하는 함수를 나타냅니다.

----------------------------------------------------------------------
java.util.function.Consumer 설명

Java 8부터 도입된 함수형 인터페이스입니다. 단일 입력 인수를 받아 결과를 반환하지 않는 함수형 인터페이스입니다. 즉, 입력 인수를 소비하는 함수라고 할 수 있습니다.
Consumer 인터페이스는 다음과 같은 메서드를 제공합니다.
accept(T t): 입력 인수 t를 소비하는 메서드입니다. ----------------------------------------------------------------------

이전 예제에서 thenRun() 메서드를 이미 살펴보았습니다. thenRun() 메서드는 데이터가 흐름에 중요하지 않은 경우 향후 완료를 처리하는 데 사용할 수 있습니다.
You have already seen the thenRun() method from previous examples. The thenRun() method can be used to handle future completions in case the data is not crucial to your flow:
Runnable 내에서 호출을 차단하는 경우 사용자 정의 Executor 에서 Runnable을 실행해야 한다는 점을 명심하세요.
Keep in mind to execute the Runnable on a custom Executor if you are doing blocking calls within the Runnable.

언급할 가치가 있는 또 다른 연결 방법은 둘 중 하나 또는 연결입니다.
CompletionStage<T>에서는 두 가지 …Either() 메서드를 사용할 수 있습니다. 전체 참조는 Java 8 API 문서를 참조하세요. 양자택일 패턴은 완료된 첫 번째 future의 값을 사용합니다. 좋은 예는 동일한 데이터를 반환하는 두 서비스(예: 마스터-복제본 시나리오)일 수 있지만 가능한 한 빨리 데이터를 반환하려고 합니다.
Another chaining method worth mentioning is the either-or chaining. A couple of …Either() methods are available on a CompletionStage, see the Java 8 API docs for the full reference. The either-or pattern consumes the value from the first future that is completed. A good example might be two services returning the same data, for instance, a Master-Replica scenario, but you want to return the data as fast as possible:

----------------------------------------------------------------------
java.util.concurrent.CompletionStage 설명

Java 8부터 추가된 인터페이스로, 비동기 계산을 위한 추상화된 객체입니다. CompletionStage는 다음과 같은 특징을 가지고 있습니다.
    • 동기/비동기 계산을 모두 지원합니다.
    • 값을 반환하거나 예외를 발생시킬 수 있습니다.
    • 다른 CompletionStage와 조합할 수 있습니다.
CompletionStage는 다음과 같은 방법으로 생성할 수 있습니다.
    • CompletableFuture 클래스의 정적 팩토리 메서드를 사용하여 생성합니다.
    • Future 인터페이스를 구현하는 객체를 CompletionStage로 변환하여 생성합니다.
CompletionStage는 다음과 같은 메서드를 제공합니다.
    • thenApply(Function): 지정된 함수를 호출하여 값을 반환하거나 예외를 발생시킵니다.
    • thenApplyAsync: thenApply와 유사하지만, 새로운 CompletionStage를 비동기적으로 실행합니다.
    • thenCompose(Function): 지정된 함수를 호출하여 다른 CompletionStage를 반환합니다.
    • thenAccept(Consumer): 지정된 소비자를 호출하여 결과를 소비합니다.
    • thenRun(Runnable): 지정된 Runnable을 실행합니다.
    • acceptEither() 메서드는 두 개의 CompletionStage를 인수로 받아, 두 CompletionStage 중
      먼저 완료된 CompletionStage의 결과를 Consumer 인터페이스에 전달하는 메서드입니다.

CompletionStage를 사용하는 예제 1 CompletionStage를 사용하는 예제 2 Java 9부터 Stream API와 통합되어 더욱 강력한 기능을 제공합니다.
예를 들어, 다음과 같이 Stream API와 CompletionStage를 조합하여 비동기 계산을 수행할 수 있습니다. ----------------------------------------------------------------------

Example 18. 마스터 및 복제본에서 읽고 첫 번째 응답 계속
Read from Master and Replica and continue with the first response

5. 에러 처리 Error handling

오류 처리는 모든 실제 응용 프로그램에 없어서는 안 될 구성 요소이므로 처음부터 고려해야 합니다. Future는 오류를 처리하기 위한 몇 가지 메커니즘을 제공합니다.
Error handling is an indispensable component of every real world application and should to be considered from the beginning on. Futures provide some mechanisms to deal with errors.

일반적으로 다음과 같은 방식으로 대응하기를 원합니다.
In general, you want to react in the following ways:
• 대신 기본값을 반환합니다. Return a default value instead
• 백업 퓨처를 사용하세요. Use a backup future
• 퓨처를 다시 시도하세요. Retry the future

RedisFuture<T>의 전송 예외가 발생한 경우.
get() 메소드에 대한 호출은 ExecutionException 내에 래핑된 발생한 예외를 발생시킵니다(이것은 Lettuce 3.x와 다릅니다). CompletionStage의 Javadoc에서 자세한 내용을 확인할 수 있습니다.
RedisFuture<T>s transport exceptions if any occurred.
Calls to the get() method throw the occurred exception wrapped within an ExecutionException (this is different to Lettuce 3.x). You can find more details within the Javadoc on CompletionStage.

다음 코드는 handler() 메서드를 사용하여 예외가 발생한 후 기본값으로 대체됩니다.
The following code falls back to a default value after it runs to an exception by using the handle() method:
Example 19. Future listener receiving result and error objects 더 정교한 코드는 exceptionally() 메서드를 사용하는 간단한 예와 같이 throw 가능한 유형 대신 반환할 값을 결정할 수 있습니다.
More sophisticated code could decide on behalf of the throwable type that value to return, as the shortcut example using the exceptionally() method:
Example 20. Future recovery with Exception handlers future를 재시도하고 future를 사용한 복구는 Java 8 CompletableFuture<T>의 일부가 아닙니다. 예외를 처리하는 편리한 방법은 Reactive API를 참조하세요.
Retrying futures and recovery using futures is not part of the Java 8 CompleteableFuture<T>. See the Reactive API for comfortable ways handling with exceptions.

6. Examples

Example 21. Basic operations Example 22. Waiting for a future with a timeout Example 23. Using a listener with RedisFuture


Async 소스

Java Lettuce를 사용한 비동기(Async) 명령 사용법입니다.

Redis8_Async.java


<< Common Keys Async Pipelining >>

Email 답글이 올라오면 이메일로 알려드리겠습니다.