producer - consumer패턴은 멀티스레드 디자인 패턴에서 많이 사용되는 패턴 중 하나이다.
한쪽은 producer의 역할. 즉, 어떤 작업을 생성해주는 역할을 하고
나머지 한 쪽은 consumer역할. 생성된 작업을 수행해주는 일을 한다.
그 중간 연결 매개체 역할을 queue가 수행한다.
producer ---> queue ---> consumer
작업생성 작업수행
다시 말해 producer는 작업 생성 후 queue에 해당 작업을 넣어주는 일만 하고,
consumer는 queue에 들어있는 작업을 꺼내서 작업을 수행하는 일만 한다.
여기서 멀티스레드가 사용되는 부분은 어디일까.
producer와 consumer를 각각 멀티스레드로 돌릴 수 있다.
producer consumer
producer ---> queue ---> consumer
producer consumer
다음 예로 멀티스레드 적용시 장점을 살펴보자.
producer가 한 작업 생성에 평균 10초가 걸리고,
consumer가 한 작업 수행에 평균 30초가 걸린다고 하자.
생성해야 하는 작업은 총 4개가 있다고 한다면,
(queue에 넣거나 가져오는데 걸리는 시간은 0초라고 가정하자.)
단일 producer, 단일 consumer일 경우엔
producer는 계속 작업생성만 하므로 0~30초가 걸릴 것이고,
consumer는 0~10초는 기다리다가 10초 이후 queue에 작업이 들어오므로 10~100초까지 작업수행을 할 것이다.
즉, 총 소요시간은 100초이다.
다중 producer, 다중 consumer일 경우엔 (각각 3개씩이라고 가정하자)
producer 3개가 각각 작업을 생성하므로 0~10초가 걸릴 것이고,
consumer 3개 또한 0~10초는 기다리다가 10초 이후 queue에 들어온 작업을 수행하므로 10~40초까지 작업을 수행할 것이다.
즉, 총 소요시간은 40초이다.
여담으로 producer-consumer가 아닌 동기방식의 작업이었다면,
작업 생성 10초 - 작업 수행 30초, 작업 생성 10초 - 작업 수행 30초, 작업 생성 10초 - 작업 수행 30초
이렇게 반복이 되므로
총 120초가 걸렸을 것이다.
즉 장점은 멀티스레드를 활용하여, 작업시간을 효율적으로 줄일 수 있다.
역할의 분리라는 장점 또한 가져올 수 있을 것이다.
하지만 단점 또한 존재한다.
1. 멀티스레드 환경이기 때문에, 동기화 문제가 발생할 수 있다.
2. consumer가 작업을 수행하다 실패할 경우, 해당 작업을 어떻게 처리할지 결정해주어야 한다.(이건 단일 스레드나 동기방식의 작업도 하긴 해야한다.)
3. 동기방식의 구현보다 복잡해질 수 있다.
동기화 문제를 해결하기 위해서 Java에선 synchronized나 BlockingQueue등을 사용할 수 있다. (비관적 동시성 제어)
하지만 너무 방어적으로 코딩을 할 경우, 멀티스레드를 쓰는 의미(성능 향상)가 줄어들 수 있어서 낙관적 동시성 제어(Atomic)를 할 수 있다.
결론은 producer-consumer패턴을 이용하여 멀티스레드 환경을 구성할 수 있으며,
작업 효율성 증가라는 장점이 있지만, 동기화 문제, 구현의 복잡성이라는 단점이 있을 수 있다.
아 Apache Kafka를 주로 사용한다고 한다.
'살짝 정리' 카테고리의 다른 글
AWS Cloud Practitioner Essentials 모듈1 (0) | 2021.06.29 |
---|---|
컴포넌트의 내부 구현을 숨기자 (0) | 2021.06.26 |
이진탐색 (0) | 2021.06.24 |
대칭키, 비대칭키 (0) | 2021.06.10 |
JPA 관계 생각해보기 (0) | 2021.06.08 |