문제

65535보다 큰 정수 값을 안내소로 포장하기위한 시스템을 고안하려고합니다. 설명하겠습니다.

SQL Server의 ID 열을 사용하여 int32 값을 생성하는 시스템이 있으며 INT32 ID를 Ushorts로 오버플레이션하는 제작 클라이언트 API에 의해 제한됩니다. 다행스럽게도 클라이언트는 주어진 시간에 약 20 개 정도의 사물을 가지고 있습니다. 주어진 시간에 패키지라고합시다. 일반적으로 허용되는 솔루션은 INT32 ID를 Ushorts로 번역하는 것입니다 (그리고 캐스팅을 의미하지는 않습니다. 번역을 의미하지는 않습니다).이 접근법에는 미늘이 있습니다.

  1. 65535 미만의 일부 ID는 비 홍수로 인해 언제든지 주어진 클라이언트에서 플레이 중일 수 있습니다.
  2. ID 충돌이있을 수 없습니다. 즉 패키지 ID 1이 클라이언트에 이동하는 경우 65536에 적용될 때 65535가 int32에서 제거되는 횟수를 추적하는 알고리즘은 65536에 적용될 때 1을 초래하여 1이 충돌 할 수 있습니다.
  3. 우리는 반품시 INT32로 Ushort를 재구성 할 수 있어야합니다.

이 문제를 해결하기 위해 사용할 수있는 것은 우리에게 반향을 일으키는 단일 서명 바이트 필드입니다. 이것을 여기에서 "바이트 필드"라고 말할 것입니다.

우리는 세 가지 번역 루틴에 대해 논의했습니다.

  1. 곱셈 : 바이트 필드에 저장 INT32에서 65535를 몇 번 제거하여 Ushort를 만들 수 있습니다. 위에서 설명한대로 충돌 문제가 있습니다.
  2. 직렬화 된 세션 상태 : 각 클라이언트의 경우 해당 클라이언트에 대한 사실을 기반으로 세션 ID를 생성하십시오. 그런 다음 클라이언트가 서버에 다시 액세스 할 때 패키지 인벤토리를 알려진 데이터베이스 ID로 다시 번역 할 수 있습니다. 직렬화 된 세션 상태를 데이터베이스로 뒷받침하기 때문에 오버 헤드 문제가 있으며 수백 ~ 수천 개의 트랜잭션을 2 초 동안 지원하려고합니다.
  3. 바이트 필드가 int32를 가져 와서 Ushort로 변환하는 변환 알고리즘의 ID 인 다양한 알고리즘 접근법. 분명히 많은 사람들은 간단한 곱셈 (우리가 변환 할 수있는 ID의 천장을 높이기 위해)이 될 것이지만, 일부는 더 작은 경계 (32768)를 사용하여 숫자가 추가되어/suptract가 형제들 사이에서 독특한 보장 할 수있는 숫자. 이 접근법은 프로세서 집약적이지만 확장 가능성을 유지하면서 충돌을 피할 수 있어야합니다 (이 접근법을 사용하면 업그레이드로 인해 Ushort 문제가 자체적으로 사라지기 전에는 도달하지 못하는 천장이 제한되어 있습니다).

그래서 내 질문은 : 위의 접근 방식보다 더 좋은 방법이 있습니까? 그렇지 않은 경우, 주어진 숫자가 더 큰 경우 1-65535 사이의 숫자를 생성하기 위해 알고리즘 (접근 #3)에서 무엇을 찾고 있습니까? 0 일방적 인 방법이 아니어야합니까?

설명 : Ushort 천장이 가장 큰 문제가 아니라 클라이언트 API가 Ushort를 사용하므로 클라이언트의 바이트 필드를 결합하여 더 큰 값을 얻을 수 없다는 것입니다 (클라이언트 API는 업그레이드 할 수 없지만 결국 존재하지 않습니다. ).

도움이 되었습니까?

해결책

접근 2에 관한 :

두 번째 접근 방식은 NAT의 작동 방식입니다. 로컬 네트워크의 모든 TCP/UDP 클라이언트는 최대 65535 포트 (포트 0 제외)와 개인 IP를 가지고 있습니다. 라우터는 단일 공개 IP 만 알고 있습니다. 두 클라이언트는 둘 다 소스 포트 300을 가질 수 있으므로 개인 IP를 공개 IP로 바꿀 수는 없으므로 충돌이 나타납니다. 따라서 IP를 대체하고 포트를 "번역"합니다 (NAT : 네트워크 주소 번역). 반환하면 포트를 다시 번역하고 패키지를 다시 전달하기 전에 대중을 개인 IP로 다시 대체합니다. 당신은 그 외에는 아무것도하지 않을 것입니다. 그러나 라우터는 해당 정보를 메모리에 보관하고 NAT를 수행 할 때 너무 느리지 않습니다 (수백 개의 컴퓨터가있는 회사는 때때로 인터넷에 나오고 대부분의 경우 속도가 눈에 띄지 않습니다). 당신은 당신이 초에 최대 수천 개의 거래를 원한다고 말하지만 얼마나 많은 고객이있을 것인가? 이것은 주로 매핑을 백업하는 데 필요한 메모리의 크기를 정의합니다. 클라이언트가 너무 많지 않은 경우 메모리에 정렬 된 테이블을 사용하여 매핑을 유지할 수 있습니다.이 경우 속도는 가장 작은 문제가됩니다 (테이블은 더 커지고 메모리가 부족한 서버가 더 큰 것입니다).

나에게 조금 불분명 한 것은 당신이 한 번 말한다는 것입니다.

다행스럽게도 클라이언트는 주어진 시간에 약 20 개 정도의 사물을 가지고 있습니다. 주어진 시간에 패키지라고합시다.

그러나 당신은 말합니다

65535 미만의 일부 ID는 비 홍수로 인해 언제든지 주어진 클라이언트에서 플레이 중일 수 있습니다.

두 번째 진술의 의미는 클라이언트가 ID 65536을 요청하면 여전히 65535 미만의 ID가있을 수 있으며 이는 (예라고 말하면) 20. 클라이언트가 ID를 처리하는 것은 아닙니다. 스트레이트 순서, 맞습니까? 따라서 65536을 요청했기 때문에 값이 작은 값을 가질 수 있지만 확실히 1-1000 범위는 아니라고 말할 수 없습니다. 실제로 20, 90, 2005 및 41238에 대한 참조를 유지하고 여전히 65535를 넘어갈 수 있습니다. 그것이 당신이 의미하는 바입니다.

나는 개인적으로 세 번째 접근 방식보다 두 번째 접근 방식을 좋아합니다. 어쨌든 충돌을 피하는 것이 더 쉽고 숫자를 다시 번역하는 것은 평범하고 간단한 작업이기 때문입니다. 세 번째 접근 방식이 장기적으로 작동 할 수 있다고 의심합니다. 좋아, 당신은 숫자의 2^16을 얼마나 자주 빼고 저장할 바이트가있을 수 있습니다. 그러나 117 * 2^16을 가장 큰 숫자로만 빼낼 수 있습니다. 숫자가 그 이상으로 올라가면 어떻게 하시겠습니까? 다른 알고리즘을 사용하여 빼지는 않지만 무엇을합니까? 나누다? 시프트 비트? 이 경우 세분화를 잃는 경우이 알고리즘은 때리다 더 이상 가능한 숫자 (큰 점프를 할 것입니다). 32 비트에 마법 번역 함수를 적용하여 16 비트에서 16 비트를 만들고 다시 변환하는 것이 쉽다면이 세상의 모든 압축 방법을 사용할 수 있다고 생각하십시오. 32 비트 수가 무엇이든간에 항상 24 비트 (16 비트 + 1 바이트)로 압축하십시오. 그것은 마법 일 것입니다. 32 비트를 24 비트로 포장하고 모든 로직을 다시 전환하는 방법을 포장 할 수는 없습니다. 외부 저장소가 필요하므로 두 번째 접근 방식으로 돌아갑니다. 이것은 작동하는 유일한 접근법이며 32 비트 번호 범위의 모든 숫자에 대해 작동합니다.

다른 팁

몇 가지 다른 옵션을 생각할 수 있습니다.

데이터베이스에 전 세계적으로 65536보다 적은 항목이 있습니까? 그렇다면 세션 상태와 관련이 없지만 응용 프로그램의 일부가 지속되는 매핑 테이블을 유지할 수 있습니다.

인덱스의 대부분의 항목은 50,000보다 적습니까? 이 경우 그러한 값을 직접 매핑하고 나머지 값에 대해 세션과 관련된 맵을 사용할 수 있습니다.

이러한 세션 데이터를 지속시키는 것이 문제이고 클라이언트 수가 합리적으로 작 으면 클라이언트/세션 선호도를 활성화하고 서버에 로컬로 구성된 맵을 유지할 수 있습니다.

웹 응용 프로그램이 아닌 경우 클라이언트 자체의지도를 유지할 수 있습니다.

충돌을 피할 수있는 알고리즘 방식은 보이지 않습니다. 충돌 할 예제를 항상 생각해 낼 수 있다고 생각합니다.

65535보다 "더"얼마나 필요합니까? "바이트 필드"에서 항상 ID의 고차 비트로 몇 비트를 추가 할 수 있습니다. 2 비트만으로 262,143, 3 비트는 524,287을 얻을 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top