무작위로 뽑기로 했으니 드물게 겹칩니다. 사용률이 1퍼센트 미만이라 100번에 한 번 미만입니다. 드문 일을 어떻게 다루는지가 이 절의 주제입니다.
확인하고 저장하면 틈이 생긴다
"이 키가 있는지 확인하고 없으면 저장한다" 는 두 단계입니다. 그 사이에 다른 요청이 같은 키를 저장할 수 있습니다.
초당 100 규모에서 이 틈이 실제로 걸리는지 계산해 봅니다. 겹칠 확률이 1퍼센트 미만이고 그중 두 요청이 같은 순간에 겹치는 것은 훨씬 드뭅니다. 드물지만 0이 아니고, 걸리면 링크 하나가 다른 대상으로 덮입니다.
사용자는 자기 링크가 남의 사이트로 가는 것을 보게 됩니다. 되돌릴 수 없는 종류의 오류입니다.
조건부 저장으로 저장소가 판정하게 한다
확인과 저장을 하나의 연산으로 만듭니다. "이 키가 없을 때만 저장" 을 저장소에 맡기면 둘 중 하나만 성공합니다.
가: 성공
나: 실패. 다시 뽑아 다시 시도
실패한 쪽은 새 키를 뽑습니다. 사용자는 그 사실을 알 필요가 없습니다.
키에 유일 제약을 걸어 두는 것이 가장 단순한 구현입니다. 제약 위반을 재시도 신호로 다룹니다.
재시도 횟수에 상한을 둔다
몇 번을 다시 뽑아도 계속 실패하면 두 가지 중 하나입니다.
| 원인 | 신호 |
|---|---|
| 키 공간이 예상보다 많이 찼다 | 실패율이 서서히 오른다 |
| 무작위 생성기가 고장났다 | 실패율이 갑자기 치솟는다 |
두 경우 모두 사람이 알아야 합니다. 그래서 상한을 두고 넘으면 오류로 응답하며 경보를 올립니다. 무한히 재시도하면 그 요청이 서버 자원을 붙잡고, 원인은 감춰집니다.
재시도 횟수는 지표로도 남깁니다. 평균 시도 횟수가 곧 키 공간 사용률의 실측값이라 길이를 늘려야 할 시점을 알려 줍니다.
덮어쓰기를 절대 허용하지 않는다
키 저장에서 덮어쓰기를 허용하면 이 모든 장치가 무의미해집니다. 조건부 저장의 반대가 덮어쓰기입니다.
그리고 만료된 키를 되살리는 경로도 같은 위험을 만듭니다. 만료 처리와 새 발급이 같은 키를 다룰 수 있기 때문입니다. 이 문제는 마지막 개념에서 다룹니다.
사용자 지정 키가 들어오면
요구사항에서는 범위 밖이지만 나중에 추가될 수 있습니다. 그때는 사용자가 고른 키와 우리가 뽑는 키가 같은 공간을 씁니다.
미리 준비할 것은 하나입니다. 조건부 저장이 이미 있으면 사용자 지정 키도 같은 경로로 처리되고, 겹치면 사용자에게 "이미 쓰이는 키" 라고 알리면 됩니다. 구조가 준비돼 있으면 기능 추가가 작은 일이 됩니다.