• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

스레드 락에 관한 질문입니다.

20.06.28 12:30 작성 조회수 479

1

안녕하세요. 공부하면서 다시 질문이 생겨 문의 드립니다. 다음강의때 언급될 내용인건지 모르겠는데 본강의에도 언급이 되어서.. sql 서버를 스레드에서 접근하게 되면 내부적으로 알아서 처리하기에 락이 필요없다고 하셨는데. 혹시 sql 변수자체도 전역변수하나를 동시에 접근해서 사용해도 되는지요? 아니면 스레드로컬변수로 스레드당 하나씩 생성해야 되는걸까요? 개인적인 생각에는 처음 할당 초기화때만 동기화에 조심해야 되는걸까 싶습니다. 그리고 레디스 변수도 똑같은 질문을 드립니다(레디스도 내부 처리는 알아서 동기화 해주는걸로 알고 있습니다). 여튼 바쁘신 와중에도 강의 꾸준히 올려주셔서 감사드리며 다음 강의도 손꼽아 기다리고 있겠습니다.

답변 4

·

답변을 작성해보세요.

3

ConnectionPool이라고 공식적으로 뭔가가 있는 것은 아니고,
그냥 DB 연결을 여러개 만들어서 돌려 쓴다는 의미였습니다.

Redis는 요약하신 내용이 맞습니다.
INCR 등은 atomic 연산을 보장하니 멀티쓰레드 개념이 없다 볼 순 없지만,
컨텐츠 스레드에서 set 명령어를 각기 다른 값으로
동시에 호출하는 것은 로직상 매우 이상할 수 있겠죠.
물론 MMO 컨텐츠 코드에서는 RDBMS 비중이 99.99%이기 때문에,
Redis에 직접 접근해서 딱히 뭘 수정할 일이 그리 자주 생기진 않을겁니다.
(어차피 MMO 서버 자체가 메모리 캐시 역할도 겸하기 때문에, 웹서버와 달리 Redis 비중이 낮습니다.)

3

[sql 변수]라는 것이 [코드에서 DB를 연결하는 DB Connection]을 말씀하시는거라면,
전역으로 둘 수는 없고 실제 사용하는 쓰레드 개수만큼 여러개를 만들어줘야 합니다.
나중에 실제로 서버에서 DB를 이용할 땐
서버 코드에서 SQL을 하나 하나 날리는 형태가 아니라,
DB쪽에 일종의 SQL 함수 개념인 StoredProcedure(SP)로 만들어놓고,
서버 코드에서는 호출할 SP를 세부 인자들과 DB쪽으로 전송하게 됩니다.

이 부분에서 request/response 정보를 정상적으로 주고 받으려면
Connection을 쓰레드 별로 구분을 해줄 필요가 있습니다.
다만 보통 쓰레드 별로 할당하진 않고, ConnectionPool을 만들어서
특정 쓰레드에서 DB로 뭔가 요청하고 싶을 때 ConnectionPool에서
빼서 쓰고 반환하는 식으로 많이 사용합니다.
참고로 게임 전투 로직을 처리하는 쓰레드는 그 자체로도 항상 바쁘기 때문에
DB를 직접적으로 처리하지 않는 것이 좋고,
DB를 담당하는 쓰레드를 따로 두거나,
DB를 담당하는 분산 서버를 두고 요청을 그쪽으로 보내는 경우가 많습니다.

이 부분이 살짝 개념으로 이해하기 어려운데,
MMO 개발 기간과 난이도가 일반 싱글 게임에 비해 10배 높은 이유이기도 합니다.
예를 들면 [몬스터를 잡아서 아이템이 드랍 되었다!]는 간단한 요구사항이 있을 때

싱글 게임이라면
(1) 클라 메모리에 아이템 생성;
~만 하면 끝나는데,

MMO의 경우
(1) 게임 서버에서 아이템 정보를 담아 DB 담당 서버에게 해당 아이템 생성 요구
(2) DB 담당 서버에서 받은 인자 정보를 이용해 SP 호출
(3) DB 요청이 완료되면 DB 서버에서 게임 서버로 response
(4) 게임 서버에서 아이템 생성 정보를 받아 인벤토리에 넣고, 플레이어 클라에게 통보
(5) 클라에서 UI 표시
~이런 식으로 단계가 복잡하게 나뉘게 됩니다.
무턱대로 DB 요청이 완료되기 전에 게임 서버 메모리에 아이템을 넣게 되면,
다음 클라 요청에 의해 아이템 정보가 꼬일 수 있기 때문에 반드시 DB 처리를 기다려주게 됩니다.

마지막으로 레디스의 경우 MMO 게임 서버 컨텐츠랑은 크게 상관없고,
대부분 웹/게임 서버 사이의 통신에서 사용되는 경우가 많습니다. (예를 들면 특정 유저의 세션 인증 토큰 등)
멀티쓰레드 환경에서 Redis를 동시다발적으로 이용한다고 크래시가 나진 않지만,
애당초 특정 키를 get/set하는 방식이기 때문에
컨텐츠 코드에서 락처리 없이 동일한 값을 set할 경우,
처리 순서에 따라 로직이 달라질 수 있습니다.

0

rush님의 프로필

rush

질문자

2020.06.30

답변 감사드립니다. 많은 도움이 되었습니다.

0

rush님의 프로필

rush

질문자

2020.06.29

자세한 답변 너무 감사드립니다. ConnectionPool을 찾아 공부해보겠습니다. 그리고 레디스 커넥션 변수는 다중스레드에서 get set 시 크래시는 나지 않고 atomic한 작업은 보장하지만 스레드의 순간적인 작업으로 순서를 직관적으로 판단할수 없으니 주의 하라는 말씀으로 알아들으면 되는 걸까요?