티스토리 뷰
티켓서비스로 불리는 이것은 pk로 사용가능한 전역적으로 유일한 interger value(GUID)를 제공해주는 방법입니다
데이터베이스 분산처리를 위해 샤딩을 하게 되면
샤딩한 데이터베이스간의 키의 충돌을 막는것이 가장 우선한 일입니다
mysql의 auto increment 컬럼을 pk로 사용하는것은 모두가 매우 잘 알고 있는 방법이지만
여러개의 데이터베이스가 물리적 또는 논리적으로 구분되어있을때
물리적, 논리적으로 구분된 데이터베이스간의 유일함을 보장하지는 못합니다
(1번 db도 row가 1부터 증가하고, 2번 db도 1부터 증가하면 계속해서 데이터베이스간의 중복된 키가 생기게 됩니다)
잘 알려진 복잡한 키값을 GUID로 쓰는 방법도 있는데 대부분의 GUID는 크고, 이것은 mysql 인덱싱에 좋지 않습니다.
mysql을 빠르게 유지하는 방법중의 하나는 인덱싱을 하고, 인덱스를 활용한 쿼리를 사용하는 것인데
인덱스의 사이즈 역시 중요한 고려사항입니다
인덱스를 메모리에 담지 못한다면 데이터베이스를 빠르게 유지할수 없기 때문입니다
GUID/샤딩 이슈를 방지하기 위해 consistent hashing 과 같은 방법을 사용할수도 있지만
이 방법은 "쓰기"가 저렴한 환경에서 사용하기 적합하고, mysql은 쓰기보다는 읽기에 최적화되어있습니다.
여러개의 데이터베이스간에 mysql auto-increment를 만들면 중복으로 인해 GUID처럼 사용할수가 없다면
하나의 db만 사용하여 만들어보는건 어떨까요?
누군가 이미지를 업로드한다거나 이런 행위가 매번 발생할때
새로운 row를 하나의 데이터베이스에 insert하고
그때 자동 생성된 auto increment id를 가지고
모든 데이터베이스의 테이블에 저장할때 이 값을 pk로 쓰면 어떨까요?
mysql에는
REPLACE INTO ...
INSERT ON DUPLICATE KEY UPDATE ...
이러한 구문이 있습니다
REPLACE는 INSERT와 비슷한데
오래된 row가 테이블에 있을때
새로운 row가 primary key 또는 unique index가 중복으로 들어올때 오래된 row는 삭제되고 새로운 row가 insert되는 기능입니다
이 동작은 데이터베이스에서 하나의 row에 원자적으로 업데이트가 가능하다는것이고
이 방식을 통해서 매번 새로운 auto-increment primary id를 얻을수 있습니다
이값을 GUID처럼 활용하는것 입니다
2010년 당시 flickr에서 만들었던 티켓을 위한 전용 db서버를 예로 들어봅니다
테이블의 구조는 이렇게 생겼습니다
CREATE TABLE `Tickets64` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`stub` char(1) NOT NULL default '',
PRIMARY KEY (`id`),
UNIQUE KEY `stub` (`stub`)
) ENGINE=InnoDB
SELECT * from Tickets64
이 쿼리는 해당 테이블에서 다음과 같은 결과를 리턴하게 될것입니다
id 컬럼은 auto increment 설정으로 인해 매번 숫자가 증가하합니다
+-------------------+------+
| id | stub |
+-------------------+------+
| 72157623227190423 | a |
+-------------------+------+
새로운 GUID를 얻고 싶다면 이렇게 합니다
REPLACE INTO Tickets64 (stub) VALUES ('a');
SELECT LAST_INSERT_ID();
stub이라는 필드는 unique 제약이 걸려있기 때문에
동일한 값을 넣으려고 하면 원래는 오류가 발생할것입니다
그런데 REPLACE INTO라는 구문을 통해서 데이터를 넣기 때문에
이미 저장되어있던 row는 삭제되고 새로운 row가 insert되고 이때 id pk 컬럼은 auto increment 조건으로 인해 숫자가 증가하게 될것입니다.
자 이렇게 우리는 GUID를 얻을수 있는 티켓 DB를 완성했습니다
(티켓 DB는 1개의 row가 계속해서 활용되기 때문에 용량이 증가하지 않습니다)
이제 앞으로 이 티켓 DB를 조회하여 GUID를 얻어온뒤에 해당 GUID를 PK로 하여
분산된 데이터베이스에 저장시에 활용한다면 모든 데이터베이스에 걸쳐 중복된 GUID는 나타나지 않을것 입니다
고가용성이 필요할때는 두개의 티켓서버를 만듭니다
auto increment가
하나는 홀수로 증가하도록 하고
다른 하나는 짝수로 증가하도록 합니다
TicketServer1:
auto-increment-increment = 2
auto-increment-offset = 1
TicketServer2:
auto-increment-increment = 2
auto-increment-offset = 2
라운드로빈형태로 두개의 서비스를 로드밸런싱하면 좀더 나은 고가용성을 만들수 있습니다
하나의 티겟 서버가 죽은경우 다른 하나가 계속해서 티켓을 발급할것입니다
이 경우 단지 홀수만, 또는 짝수만 있는 데이터가 매우 많이 늘어날뿐 아무런 문제가 발생하지 않습니다
이 방법은 분산 데이터베이스 환경에서 GUID를 만드는 여러 방법중에
가장 개발자가 이해하기 쉽고, 만들기 쉬운 방법입니다
flickr에서 2010년에 구현했던 티켓서비스에 대한 포스팅을 재정리해서 올려보았습니다
참고
https://code.flickr.net/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/
'WEB2.0 > 프로그래밍' 카테고리의 다른 글
무료 서버 제공주는 곳 정보 푼다 (0) | 2022.07.06 |
---|---|
mongodb ObjectId 파헤치기 (0) | 2022.06.29 |
hset을 이용하여 메모리 효율적으로 redis에 저장하기 (0) | 2022.06.27 |
캐싱(caching) 전략 (0) | 2022.06.24 |
github multi account, multiple profile 설정하기 (0) | 2022.06.22 |
- Total
- Today
- Yesterday
- 창업
- Apple
- 아이디어
- 아이폰
- 벤처
- 앱
- iPhone
- 모바일
- 애플
- 네이버
- 자바스크립트
- php
- 스마트폰
- 대학생
- 공모전
- 어플리케이션
- CSS
- 웹표준
- 경진대회
- 앱스토어
- 구글
- 트위터
- android
- AWS
- 안드로이드
- 소프트웨어
- JavaScript
- 게임
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |