주요 콘텐츠로 건너뛰기

CAC는 VOS 메시지 큐의 문제를 자주 조사하라는 요청을 받습니다. 다음은 몇 가지 흥미로운 것들과 함께 몇 가지 솔루션및 권장 사항과 함께 귀하와 공유하고 싶습니다.

문제 1: 최근에는 고객이 문제를 해결해 왔습니다. 요청자는 메시지 큐에 메시지를 추가할 수 없었고 오류 코드 e$max_file_exceeded 받았습니다. 이상하게도 list_messages 명령에 표시된 것처럼 큐가 비어 있었습니다.

큐를 검사할 때 이 큐에 사용된 디스크 블록 수가 비익 범위 파일에 대한 최대 파일 크기에 접근하는 것으로 나타났습니다.

이름: %s1#d01>AppData>큐. Mq

파일 조직: 메시지 큐 파일
마지막 사용: 11-08-16 14:45:13 edt
최종 수정: 11-08-16 14:45:13 edt
마지막 저장: 10-06-14 21:34:18 edt
생성 시간: 10-06-09 11:03:15 edt
트랜잭션 파일: 예
로그 보호: 아니요
안전 스위치: 없음
감사: 아니요
동적 범위: 아니요
범위 크기: 1
마지막 메시지: 51689380
사용 된 블록 : 520201
...

이 큐가 가득 찼고 비어 있는 이유는 무엇입니까?

과거 어느 시점에서 큐에서 메시지를 빼내는 서버는 오프라인이었습니다. 이로 인해 메시지백로그가 매우 커졌습니다. 이러한 메시지는 결국 서버에서 처리되고 큐에서 삭제되었습니다. 큐에서 메시지가 삭제되면 큐의 _record_index 인덱스에 키가 추가되고 키 값은 삭제된 메시지의 바이트 수를 나타냅니다.  새 메시지가 메시지 큐에 추가되면 파일 시스템은 새 메시지의 정확한 크기의 이전에 삭제된 메시지를 찾으려고 시도합니다. 사용할 수 없는 경우 새 메시지는 큐 끝에 있는 처녀 공간에 기록됩니다.

이 경우 새 메시지를 포함할 수 있는 처녀 공간이 충분하지 않았으며 올바른 크기의 기존 삭제 메시지가 없었습니다.

이 이야기의 교훈은 지정된 큐의 고유한 메시지 길이 수를 제한하는 것이 좋습니다. 각 메시지가 필요한 정확한 바이트 수를 사용하는 대신 값을 일부 표준 크기로 반올림합니다. 이 기술을 사용하면 새 메시지가 이전에 삭제된 메시지에서 공간을 재사용할 수 있는 가능성이 높아진다.

문제 2: 최근에는 메시지 큐의 성능에 대한 또 다른 상황이 발생했습니다. 한 고객은 400,000개 이상의 메시지 큐를 비우는 데 시간이 지나치게 많은 시간이 소요되었다고 말했습니다.

최근에는 서버 프로세스가 메시지 큐에서 적시에 메시지를 처리할 수 없는 데 문제가 있었습니다. 다행히도 요청자는 데이터가 손실되지 않도록 계속 실행되었습니다. 서버 문제가 해결되었을 때 백로그 된 요청을 따라 잡기 까지는 여러 시간이 걸렸고 최근 트랜잭션 처리를 시작할 수 있었습니다. 고객은 왜 이런 일이 일어났는지, 그리고 향후 상황에서 어떻게 방지하거나 속도를 내수 있는지 물었습니다.

메시지 큐에서 메시지가 삭제되면 키의 값이 메시지 길이인 시스템 유지 관리 _record_index 키가 추가됩니다. 삭제되는 메시지가 이전에 삭제된 메시지와 동일한 길이인 경우 사용되지 않는 데이터 위치는 중복 값 목록의 끝에 해당 메시지 크기를 포함하는 키의 중복 항목으로 저장됩니다. 따라서 수십만 개의 삭제된 메시지가 있는 경우 모두 동일한 크기(또는 삭제된 메시지 의 길이 집합이 작음) 중복 키 목록이 매우 길고 단일 메시지를 삭제하는 시간이 선형으로 올라갑니다.

반대로 메시지가 큐에 추가되고 메시지 길이에 대한 _record_index 키가 존재할 때 새 메시지에 대한 데이터를 포함하도록 최신 삭제된 레코드가 차지하는 공간이 다시 사용됩니다. 그런 다음 이 값을 메시지 길이를 포함하는 키 값에서 삭제해야 합니다. 따라서 메시지를 추가하는 시간은 선형으로 올라갑니다. 삭제된 메시지가 많을수록 새 메시지를 추가하는 데 시간이 오래 걸립니다.

이 이야기의 교훈은 메시지 큐에서 시스템을 유지 관리하는 데이터에 메모리가 있다는 것입니다. 큐는 이전 모든 메시지의 위치와 크기를 기억합니다. 이 정보는 큐가 비워진 후에도 유지됩니다. 메시지 큐가 거대한 크기(수만 또는 수십만 개의 디스크 블록)로 증가하도록 허용하지 않도록 하십시오. 그렇지 않으면 큐에 메시지를 추가하고 삭제하는 비용이 시간이 지남에 따라 증가할 수 있습니다.

이러한 두 상황에 대한 해결책은 동일합니다.

솔루션 A: 메시지 큐를 여는 동안 잘릴 수 있습니다. 루틴 s$truncate_queue 이 작업을 수행하는 데 사용할 수 있습니다. 그러나 만족해야 할 4가지 조건이 있습니다.

1: 메시지 큐를 열어 두는 요청자가 없어야 합니다.

2: 메시지 큐는 모든 메시지의 배수되어야 합니다.

3: 이 루틴은 서버에서 호출해야 합니다.

4: 큐는 트랜잭션 파일이 될 수 없습니다.

처음 3가지 조건이 충족되지 않으면 s$truncate_queue e$no_truncate_queue 반환됩니다. 마지막 조건이 충족되지 않으면 s$truncate_queue e$invalid_io_operation 반환됩니다.

솔루션 B: 응용 프로그램 디자인으로 여러 서버가 있는 경우 기존 메시지 큐의 이름을 주기적으로 변경하고, 올바른 이름으로 새 메시지 큐를 만들고, 새 서버 집합을 시작하고, 요청자를 반송할 수 있습니다. 서버가 시작되면 새 하지만 비어 있는 메시지 큐에서 처리를 시작합니다. 요청자가 시작하면 새 및 빈 메시지 큐에 요청을 추가합니다. 원래 서버 집합은 큐가 비어 있는 때까지 요청의 백로그를 처리하면서 실행 중인 상태로 유지될 수 있습니다. 그런 다음 이전 서버 집합을 중지할 수 있으며 이전 메시지 큐를 삭제할 수 있습니다.

또한 문제 1에 대한 해결책은 범위 기반 메시지 큐를 사용하는 것일 수 있다. 이를 통해 최대 파일 크기가 범위 크기의 계수에 따라 더 커지기 때문에 추가 메시지를 큐에 배치할 수 있습니다. 그러나 익스텐트 메시지 큐를 사용하면 메시지 큐에 한 번에 많은 수의 메시지가 포함된 경우 성능이 평소보다 더 나빠집니다.

앞에서 설명한 것처럼 지정된 큐의 고유 메시지 길이 수를 제한하면 새 메시지가 이전에 삭제된 메시지로 해제된 공간을 재사용할 수 있는 가능성이 향상됩니다. 이렇게 하면 이 게시물에 언급된 두 가지 문제를 모두 해결하는 데 도움이 됩니다.

© 2024 스트라투스 테크놀로지스.