JPA 이용할때 DB Commit 처리

286 views
Skip to first unread message

심상규

unread,
Mar 19, 2020, 3:58:01 AM3/19/20
to Korea Spring User Group Q&A
안녕하세요. 

서버에 약 10만건 정도에 자료가 존재하고

Client 에서 Rest API 로 요청 을 하면 

한번에 10만건을 보낼 수 없어서...

1000건씩 보낼려고 하는데요.

문제는 1000씩 보내면 10만건 중에 이미 보낸 건과 보내야 하는 건을 구분하기 위해서

보낸 자료에 예를 들어 Send_Flag 에 'Y' 이렇게 업데이트를 하는데요.

Client 에서 한건 다 받고 또 요청 하고 이렇게 하면 너무 느려요.

비동기식으로 호출을 합니다. 

동시에 여러번 호출이 되는거죠..

그렇게 되니깐 동일 건을 보내는 문제가 생기네요.ㅡ,.ㅡ

5번 호출 하면 5천 건이 가는게 아니라 중간에 중복되어서 4000건이 간다던지...

그래서 보내기 전에 보내야 할 1000건을 Grouping 해서 send_group 이라는 필드에 'group1' 이렇게 update 하고
group1 을 select 해서 보내는데..

보내는 와중에 요청 들어 오면 DB 에 아직 Commit 가 안되어서 인지...
이렇게 해도 중복이 되네요..

이런 경우는 어떻게 해결 할 수 있나요?



YongHyuk Lee

unread,
Mar 19, 2020, 4:01:29 AM3/19/20
to ks...@googlegroups.com
큐에 범위를 넣어서 처리하시면
예를들면 큐에다가 startIdx : 1, offset: 1000 이런식으로..
두번째큐는 startIdx: 1001, offset: 1000 


2020년 3월 19일 (목) 오후 4:58, 심상규 <hero...@gmail.com>님이 작성:
--
이 메일은 Google 그룹스 'Korea Spring User Group Q&A' 그룹에 가입한 분들에게 전송되는 메시지입니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 ksug+uns...@googlegroups.com에 이메일을 보내세요.
웹에서 이 토론을 보려면 https://groups.google.com/d/msgid/ksug/29c9a836-0ac8-4f69-afc9-98bda51ff86d%40googlegroups.com을(를) 방문하세요.
--
-----------------------------------------------

Shiny제나이드

unread,
Mar 19, 2020, 5:57:00 PM3/19/20
to Korea Spring User Group Q&A
데이터가 10만건일 경우, 리스트로 받거나 하긴 힘들겁니다. ㅎㅎ 플래그 둬서 하는 건 말씀하신 것처럼 비동기식으로 하면 커밋이 꼬여버려 단순 조회에서 엄청 열받게 하죠.

현재 thingsboard 라는 프로젝트 분석을 어느정도 미쳤고, 거기에서 사용하는 방식을 설명드릴게요.

Restful api를 담당하는 계층부터 실제 crud 하는 계층까지 총 4단계로 구분해놨습니다만, 원하신다면 계층은 줄일 수 있으실 거 같고. 아무튼 각설하고 본론으로 들어오겠습니다.

Controller (restapi request mapper)
Service (각 target object별로 생성)
Dao (실제 db호출 데이터 가공 단계)
Repository (JPA based crud)

여기에서 repository 단계부터 반환하는 변수형을 TextPageData<?> 으로 줘서 갯수제한을 실현했습니다. 뭐 한 페이지가 1000개 보여준다면, 다음 페이지도 남은 거 중에 1000개 이렇게요.

10만건이든 1000만 건이든 1000건이든 데이터베이스 입장에서 풀 스캔은 어차피 쿼리 때마다 수행되므로 (딱히 인덱스를 사용하지 않는 이상) 비동기로 호출하시되, 쿼리는 딱 한 번만 하시는 걸 추천.

참고할 수 있는 기트 경로 붙일게요.

https://github.com/thingsboard/thingsboard/blob/master/application/src/main/java/org/thingsboard/server/controller/DeviceController.java


여기에서 키워드는 TextPageData 로 하시고, repository 계층까지 내려가보시면 도움될겁니당.
Repository 파일은 제일 상단프로젝트 중 Dao에 있어여

Mark Sunghun Park

unread,
Mar 25, 2020, 4:19:20 AM3/25/20
to ksug
제가 백엔드를 주로 하는 게 아니라서 아주 정확한 거는 말씀드릴 수 없지만 엔지니어링란게 사실 기본은 같은 거라 아이디어는 말씀드릴 수 있을 거 같아요.
일단은 상태값을 변경하는 방법을 쓰게 되면 일이 좀 복잡해질 것 같아요. 여러 쓰레드에서 값을 변경하려고 하기 때문에 말이죠. 
따라서 큐를 하나 만드시고 보낼 데이터들을 큐에 집에 넣으세요. 같은 녀석이 이미 큐에 들어가 있으면 집어 넣지 말아야 겠죠. 큐에는 db 테이블에 있는 키값만 저장을 해도 될 것 같구요. 
비동기로 작업을 돌리더라도 전송 중복을 방지하려면 결국은 동기방식으로 보낸 것과 보내지 않을 것을 체크해야만 하겠죠.

Ki-Seok Kim

unread,
Apr 6, 2020, 3:43:10 AM4/6/20
to Korea Spring User Group Q&A
답변이 너무 늦어서 도움이 될진 모르겠네요



AMQP 를 이용하면 될거같습니다. rabbitmq 나 active mq 같은..

클라이언트에서 RESTful API 를 호출하지 말고 amqp consumer 로 작동하게 하고 서버는 적당량의 데이터만 큐로 쏴주면 rabbitmq 가 동시성 처리와 재시도 등을 처리해줍니다.

db 도 큐로 쏘고 flag 처리하면 될거같네요 성능을 더 끌어올리고 싶다면 redis queue 를 쓰면 될거같습니다.

Send_Flag 도 10만건 테이블을 alter 하시는건 아니겠죠?

별도 map 테이블에 insert 하고 exist 쿼리로 하면 확인하는것도 빨라질거같네요 db lock 문제도 해결되고.

그리고 10만건 정도면 그냥 redis 에 저장하는것도 문제 없어 보입니다. db 에 Send_Flag 할거 없이 redis transaction 검색해서 redis 에 Send_Flag 정보를 저장할수도 있습니다.




2020년 3월 19일 목요일 오후 4시 58분 1초 UTC+9, 심상규 님의 말:
Reply all
Reply to author
Forward
0 new messages