서비스 브로커-대화 평생?


9

비즈니스 사례를 해결하기 위해 환경에서 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)를 사용하고 있습니다

  1. 트리거 트리거 (낮은 지연 시간 또는 대량 전송)
  2. 대화 핸들을 찾거나 작성하십시오.
  3. 문자 보내
  4. 큐 활성화 절차
  5. 결과 테이블 업데이트

정리 프로세스는 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 개의 메시지를 처리했습니다.

우리는 물건이 무너지기 전에 너무 오래 갔기 때문에 이번에는 그렇게 할 것이라고 생각했습니다. 내일 우리는 메시지가 전선을 통과하도록 노력할 것입니다.


1
we started seeing blocks and high contention on sysdesend and the queue table.대기 유형은 무엇입니까 PAGELATCH_EX/SH and WRITELOG? 150 트릭 을 사용 했습니까 ? 시스템 테이블이 경합 지점 인 경우 150 트릭이 매우 유용합니다.
Kin Shah

@kin, 질문을 업데이트했지만 잠금 유형은 LCK_M_U 또는 LCK_M_X입니다. 150 트릭에 대해 읽었지만 2016 년에는 불필요하다고 생각했지만 (tempdb 누출 문제를 해결했기 때문에) 또한 해킹처럼 보입니다. 우리는 생산에 들어가기 위해 또 다른 찌르기를 할 것입니다 (우리는 슬프게도 생산 작업으로 만 발생합니다). 더 짧은 수명의 대화를 먼저 시도 할 것입니다. 결과를 여기에 업데이트하겠습니다. 다음은 당신이 참조 한 150 트릭입니다.
Jonathan Fite

나는 트위터에 @RemusRusanu 에게 물었다 -그는 서비스 중개인 물건에 전문가이다 :-)
Kin Shah

이것은 내가 전에 본 것이 아닙니다 (장시간 경과 후 SEND의 저하). 1) sys.conversation_endpoints테스트 중 행 수는 얼마 입니까 (일정하거나 증가하고 있으며 차단이 발생할 때의 크기). 2) 차단이 발생하면 대상 대기열을 비활성화하면 SEND 차단이 달라집니다 (큐를 비활성화하면 SEND를 sys.transmission_queue로 라우팅해야 함). 그리고 3) 로컬로 (SSB 종점 설정, 경로 추가) 메시지를 유선으로
보내면

더 많은 생각 : 4) 블로킹이 발생하면 대상에서 RECEIVE를 중지 하면 대상 큐에 고스트 레코드가 얼마나 많은지 (있는 경우 활성화 된 프로 시저 비활성화) 5) 차이 가 있습니까? ALTER QUEUE ... REBUILD차단이 시작되면 달리기 가 차이를 냅니까?
Remus Rusanu

답변:


3

본인의 질문에 대답하는 것이 나쁜 형식이라는 것을 알고 있지만 관심있는 사람을 위해이 내용을 마무리하고 싶었습니다. 마침내 문제를 해결하거나 요구 사항을 충족하기에 충분할 정도로 해결했습니다. 의견을 주신 모든 분들께 감사드립니다. 그들이 도움이 된 Remus Rusanu와 Kin.

우리 데이터베이스는 매우 바쁘고 RCSI 모드입니다. 우리는 45 초마다 위치 정보를 업데이트하는 수많은 (수천) 모바일 장치를 가지고 있습니다. 이러한 업데이트를 통해 여러 테이블의 정보가 업데이트됩니다 (변형 정보를 단일 테이블로 제한 한 다음 결과를 위해 합쳐서 설계가 잘못됨). 이 테이블은 최종 사용자가 기본 테이블을 직접 사용하지 않고보고 정보를 비동기식으로 생성하려는 것과 동일합니다.

처음에는 모든 업데이트 / 삽입 명령문 (대부분의 경우 한 행이어야 함)에서 수정 된 레코드에 대해 커서를 실행하고 메시지의 각 기본 키를 서비스 브로커에 보내는 트리거가있었습니다. 내부 서비스 브로커, 특히 벌크 큐는 보고서에 대한 업 서트 프로 시저를 실행하는 추가 커서였습니다 (기본 키당 한 번의 실행).

마침내 우리가 일하게 된 것 :

  • 커서를 제거하고 더 큰 메시지를 보내도록 설정했습니다. 테이블 당 사용자 트랜잭션 당 여전히 하나의 메시지이지만 이제 기본 키가 둘 이상인 메시지를 보냅니다.

  • 벌크 프로세서는 또한 메시지 당 여러 개의 키를 전송하여 메시지를 다른 대기열로 적절히 섞을 때 진행중인 SEND CONVERSATIONS 수를 줄였습니다.

  • 가장 변동성이 큰 테이블 (모바일 장치 데이터 테이블)에는 트리거가 제거되었습니다. 적절한 외래 키를 포함하도록 upsert 프로 시저를 업데이트했으며 이제 사용자에게 결과를 가져올 때 해당 테이블에서 다시 조인합니다. 이 표는 하루에 처리해야하는 메시지의 80 %를 쉽게 기여했습니다.

우리는 (모바일 테이블없이) 하루에 ~ 1M 개의 메시지를 처리하며 대부분의 메시지 (99 % +)는 목표 내에서 처리됩니다. 우리는 여전히 가끔 이상 치가 있지만 허용되는 것으로 간주되는 드문 특성을 감안할 때.

기여 요인 :

  • 앞에서 언급 한 대화 정리 절차에서 실제로 대화를 제대로 정리하지 못하고 조기에 끝내지 않는 버그가 발견되었습니다. 이로 인해 sysdesend 수는 수천 개를 넘지 않게되었습니다 (대부분 150 트릭을 사용하면 발생합니다).

  • 트리거의 커서는 예상보다 많은 잠금을 유지하는 것처럼 보입니다 (정적, forward_only의 경우에도). 그것들을 제거하면 SEND CONVERSATION에서 볼 수있는 잠금이 본질적으로 일시적이게됩니다 (또는 적어도 우리가 보는 시간은 훨씬 더 낮습니다).

  • 우리는 본질적으로 두 솔루션을 나란히 (Service Broker 솔루션 백엔드 (생산로드 테스트 용)) 현재 솔루션 (많은 테이블에 걸쳐있는 끔찍한 쿼리)을 실행하고있었습니다.

부작용으로, 이것은 Ghost Record Cleanup 문제를 발견했으며 Service Broker 테이블 (시스템 또는 대기열)에 있지 않은 동안 시스템에 상당히 많으며 증상이 "명확한 원인"과 잘 일치합니다. 우리가 때때로 경험하는 문제. 이에 대한 조사가 진행 중이며, 우리는 그에 기여하는 테이블을 찾으려고 노력하고 있으며 아마도 색인을 정기적으로 재구성 할 것입니다.

다시 한번 감사드립니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.