비즈니스 사례를 해결하기 위해 환경에서 Service Broker를 작동 시키려고합니다. 메시지 제목이 좋은지 모르겠지만 질문은 다음과 같습니다. 그러나 그것은 좋은 질문이 아닐 수 있습니다. 그래서 그 후에 우리가하고있는 일과 그것이 올바른 질문이라고 생각하는 이유입니다.
대화를 끝내기 전에 몇 개의 메시지를 대화로 보내야합니까?
결과 테이블을 비동기 적으로 업데이트하기 위해 Service Broker를 사용하려고합니다. 결과 테이블이 평평하고 빠릅니다. 기본 테이블에는 테이블과 기본 키와 함께 메시지를 보내는 트리거가 있습니다. 우리는 3 개의 대기열을 가지고 있습니다 :
- 낮은 지연 시간-목표는 처리하는 데 15 초입니다. 특정 항목과 관련하여 변경되는 항목을 처리합니다.
- 대량 대기열-목표는 5 분입니다. 수백 (또는 수천)의 항목에 영향을 미치는 변경 사항이있을 때 처리합니다. 영향을받은 항목의 목록을 분류하고 지연된 지연 시간이 짧은 큐에 공급합니다.
- 지연된 지연 시간-목표는 처리하는 데 30 분입니다. 이는 대량 대기열에서만 항목을 처리합니다.
기본적으로 고객의 정보가 업데이트되는 경우 많은 제품에 영향을 미치므로 처리 속도가 느려지기 위해 대량 대기열로 전송됩니다. 그러나 제품이 업데이트되면 대기 시간이 짧은 대기열로 전송됩니다.
기본 키 모듈러스를 기준으로하는 점을 제외하고 Remus Rusanu의 블로그 http://rusanu.com/2007/04/25/reusing-conversations/ 와 유사한 대화를 재사용합니다 . 이것은 기본 키의 중복 제거에 도움이되는 부작용이 있습니다.
따라서 우리는 대화를 재사용하고 지침 내에 있습니다. 두 개의 스레드를 사용하여 초당 125 개의 메시지 (수천 개의 메시지가 인위적으로 떨어짐)를 생성 할 수 있었으며 이는 프로덕션 (초당 15 개의 메시지 / 초)을 유지할 수있는 것 이상입니다.
그러나 우리가 겪고있는 문제는 ~ 4 시간 또는 120K 메시지가 지난 후 sysdesend 및 큐 테이블에서 블록과 높은 경합이 발생하기 시작했다는 것입니다. 잠금은 LCK_M_U이며 KEY 잠금입니다. 때때로 hobt는 sysdesend로 해결되고 다른 경우에는 특정 큐 테이블 (queue_)로 해결됩니다.
우리는 이미 24 시간 또는 30 분 동안 활동이 없으면 대화를 끝내는 프로세스를 갖추고 있으므로 대화를 순환하기 전에 시간을 늘릴 수 있습니다.
SQL 2016 Enterprise (13.0.4001.0)를 사용하고 있습니다
- 트리거 트리거 (낮은 지연 시간 또는 대량 전송)
- 대화 핸들을 찾거나 작성하십시오.
- 문자 보내
- 큐 활성화 절차
- 결과 테이블 업데이트
정리 프로세스는 10 분마다 실행되어 유휴 대화가 있는지 확인합니다. 연속으로 3 번 이상 발견되면 비활성으로 표시하고 대화를 종료합니다.
도움이 될만한 추가 정보가 있으면 알려주십시오. Service Broker에 대한 경험이 많지 않으므로 메시지 / 초가 낮거나 높거나 무관한지 알 수 없습니다.
최신 정보
그래서 오늘 다시 시도했지만 같은 문제가 발생했습니다. 대화 수명을 2 시간으로 변경했는데 아무런 효과가 없었습니다. 그런 다음 150 트릭을 구현했습니다. 같은 문제가 발생했습니다.
SEND CONVERSATION, sysdesend를 기다리는 톤. 더 이상의 아이디어가 있습니까?
업데이트 2
우리는 오늘 더 긴 테스트를 수행했으며 17 분의 샘플 기간 중 하나에 대해 4 개의 대화 핸들에서 41K 메시지를 처리했습니다. 우리는 sysdesend와 큐 테이블의 잠금이 너무 커져서 멈추기 전에 뒤로 표류하기 시작했을 때를 제외하고는 계속 유지할 수있었습니다. 대기열에 들어 가지 않고 메시지를 처리하는 데 아무런 문제가없는 것 같습니다. 우리는 메시지를 꺼내고 그 속도의 5 배 이상 처리 할 수 있습니다. 메시지 추가에 따라 속도가 제한되는 것 같습니다.
이후 테스트에서 메시지의 80 %를 차지하는 트리거 중 하나를 제거했습니다. 이렇게 줄어든 부하에도 불구하고 우리는 동일한 대기를보기 시작했습니다.
업데이트 3
Remus에게 조언을 해주셔서 감사합니다 (그리고 주제에 대한 훌륭한 블로그 기사를 게시 해 주셔서 감사합니다.이 시점까지 도움이되었습니다).
우리는 오늘 그것을 다시 실행하고 더 잘했습니다 (우리가 기다림을보기 전에 더 오래 걸렸고 그것이 우리를 불구로하기 전에 더 오래갔습니다). 세부 사항입니다.
다음과 같이 변경되었습니다. * 스레드 당 유지되는 대화 수가 1 : 1에서 2 : 1로 증가했습니다. 기본적으로 4 개의 스레드에 대해 8 개의 대화 핸들이있었습니다.
- 하나의 수신 메시지가 수백 개의 발신 메시지를 의미 할 수 있기 때문에 대량 대기열을 통합하여 더 적은 수의 큰 메시지로 통합했습니다.
이 시도에 대한 참고 사항 :
대상 큐 활성화 절차 비활성화 차단에 변화가 없었으며 (5 분 동안 대기) 메시지는 sys.transmission_queues로 전송되었습니다.
sys.conversation_endpoints 모니터링 이 숫자는 0 13K에서 매우 빠르게 증가한 후 하루 종일 더 천천히 증가하여 ~ 5 시간 후에 약 25K로 끝났습니다. 16K +/-에 도달 할 때까지 차단이 시작되지 않았습니다.
쿼리에서 고스트 레코드가 200 이상이어서 정리가 끝나고 카운트가 0으로 떨어지지 않았지만 DAC에 들어가서 대기열에 대한 DBREINDEX 명령을 실행했습니다.
테스트를 마쳤을 때 sysdesend와 sysdercv의 개수는 24,932로 동일했습니다.
5 시간 동안 ~ 310K 개의 메시지를 처리했습니다.
우리는 물건이 무너지기 전에 너무 오래 갔기 때문에 이번에는 그렇게 할 것이라고 생각했습니다. 내일 우리는 메시지가 전선을 통과하도록 노력할 것입니다.
sys.conversation_endpoints
테스트 중 행 수는 얼마 입니까 (일정하거나 증가하고 있으며 차단이 발생할 때의 크기). 2) 차단이 발생하면 대상 대기열을 비활성화하면 SEND 차단이 달라집니다 (큐를 비활성화하면 SEND를 sys.transmission_queue로 라우팅해야 함). 그리고 3) 로컬로 (SSB 종점 설정, 경로 추가) 메시지를 유선으로
ALTER QUEUE ... REBUILD
차단이 시작되면 달리기 가 차이를 냅니까?
we started seeing blocks and high contention on sysdesend and the queue table.
대기 유형은 무엇입니까PAGELATCH_EX/SH and WRITELOG
? 150 트릭 을 사용 했습니까 ? 시스템 테이블이 경합 지점 인 경우 150 트릭이 매우 유용합니다.