"고유 ID 생성"이라는 문제는 서버 프로그래밍을 하다보면 빈번히 마주치는 문제다.
전형적인 문제 중에 하나로서 게임 서버에서 플레이어가 사용할 아이템을 생성하는 경우가 있다. 아이템에 대한 정보를 데이터베이스에 집어넣을 때는 고유 ID가 필요하다. 물론 고유 ID 없이 집어넣을 수도 있겠지만, 운영 상의 문제 등을 위해 집어넣는 것이 좋다.
고유 ID를 사용해야 하는 객체, 즉 게임 서버가 하나라면 별 문제가 없다. 그냥 프로그램 내부에서 변수 하나 선언하고, 필요할 때마다 1씩 증가시켜가며 사용하면 되니까. 하지만 게임 서버가 여러 대라면 좀 귀찮아진다.
이런 경우, 일반적으로 가장 먼저 나오는 방법이 데이터베이스 상에서 제공하는 auto increment 기능을 이용하는 방법이다. SQL Server 같은 경우에는 @@IDENTITY 값을 이용하면, 하나의 행을 추가할 때마다 고유한 ID를 얻을 수 있다.
@@IDENTITY 값은 여러 가지 제약 사항이 있기 때문에, 데이터베이스를 이용하지 않고, ID 발급을 위한 중앙 서버를 따로 둘 수도 있다. 이에 관한 건 GPG 6권 7.3 장에 잘 소개되어 있다.
하지만 데이터베이스 또는 ID 발급 서버 같이 중앙 저장소가 따로 존재하는 경우, 데이터 생성 시점에서 고유 ID를 바로 알 수 없다는 문제점이 있다. 데이터베이스는 INSERT 후에야 고유 ID 값을 알 수 있고, 중앙 서버를 두는 경우에는 패킷이 한번 왔다갔다해야 고유 ID 값을 알 수 있다는 말이다. 이 처리가 은근히 귀찮다. 로직이 비동기 방식이 되기 때문이다.
이 문제를 해결하는 의외로 간단하다. 각각의 게임 서버에서 고유 ID 값을 1씩 증가시키는 것이 아니라 게임 서버의 갯수만큼씩 증가시키면 된다.
1번 게임 서버 : 1 --> 5 --> 9 --> ...
2번 게임 서버 : 2 --> 6 --> 10 --> ...
3번 게임 서버 : 3 --> 7 --> 11 --> ...
위에서는 0을 베이스로 삼았지만, 처음에 게임 서버가 뜰 때 데이터베이스 상에 존재하는 아이템 중에 최대값의 고유 ID를 읽어와 베이스로 삼아야한다. 즉 데이터베이스 상에 고유 ID 최대값이 379라면...
1번 게임 서버 : 379 + 1 = 380 --> 384 --> 388 --> ...
2번 게임 서버 : 379 + 2 = 381 --> 385 --> 389 --> ...
3번 게임 서버 : 379 + 3 = 382 --> 386 --> 390 --> ...
실제로 적용할 때에는 추가적으로 게임 서버가 뜨는 시간차를 고려해서 베이스 값을 보정해줘야 한다. 어쨌든 이렇게 처리하면 아이템 생성 시점에서 이 아이템에 부여할 고유 ID를 알 수 있다. 다만 모든 게임 서버의 아이템 생성 속도가 같지 않기 때문에 중간중간에 갭이 생긴다는 단점이 있다. 이는 뭐 서버 정기 점검 시간에 압축을 하거나, 64비트 값을 써버리면 된다.
알고 보면 정말 별 거 아닌 트릭이지만, 의외로 모르는 이도 있는 듯 하여 정리해 봤다.

글
댓글을 달아 주세요
댓글 RSS 주소 : http://serious-code.net/tc/rss/comment/7댓글 ATOM 주소 : http://serious-code.net/tc/atom/comment/7