사랑하는 여러분, 내부 시스템 호출, 외부 시스템 호출 또는 수동적으로 트리거되는 호출(예: MQ 소비, 콜백 실행, 등), 필요한 조건 확인을 추가해야 합니다. 이 조건은 반드시 전달될 것이고, 반드시 가치가 있을 것이며, 반드시 비어 있지 않을 것이라고 말하는 일부 동료들을 믿지 마십시오. 아니요, 설 직전에 속아서 생산사고가 나서 기본적으로 연말 보너스가 반으로 줄었습니다.
높은 시스템 가용성과 안정성을 보장하기 위해 사람보다는 코드 자체에 집중하기로 결정했습니다. 다음은 당신에게도 도움이 될 수 있는 몇 가지 작은 교훈입니다.
내 비즈니스 시나리오는 다음과 같습니다. 비즈니스 A가 변경되면 MQ 메시지 전송이 트리거되고 애플리케이션이 MQ 메시지를 수신하며 처리 후 데이터가 Elasticsearch에 기록됩니다.
(1) A업체로부터 비정상적인 알람을 받았습니다. 당시 알람은 다음과 같았습니다.
(2) 언뜻 보기에는 조금 이상해 보이지만 어떻게 Redis 예외일 수 있습니까? 그런 다음 Redis에 연결했는데 문제가 없었습니다. Redis 클러스터를 다시 확인해 보니 모든 것이 정상이었습니다. 그래서 우연한 네트워크 문제인 줄 알고 놔두었습니다.
그런 다음 기술 문제 그룹에서 일부 사용자에게 비정상적인 상황이 발생했다고 고객 서비스에 보고했습니다. 즉시 시스템을 확인하여 산발적인 문제가 있는지 확인했습니다.
(4) 그래서 습관적으로 몇 가지 핵심 구성 요소를 살펴보았습니다.
SQL이 느리고 메타데이터 잠금 시간이 긴 상황을 발견했습니다. 이는 주로 대규모 테이블의 전체 테이블 쿼리로 인해 많은 양의 데이터와 느린 실행 속도로 인해 메타데이터 잠금이 너무 오래 지속되어 지치게 되었기 때문입니다. 데이터베이스 연결 번호.
으아악(6) 여러 개의 느린 세션을 즉시 종료한 후에도 시스템이 아직 완전히 복구되지 않은 것으로 나타났습니다. 이유는 무엇입니까? 이제 데이터베이스가 정상인데 왜 완전히 복원되지 않았습니까? 계속해서 애플리케이션 모니터링을 살펴보니 사용자 센터의 Pod 10개 중 2개가 비정상이고, CPU와 메모리가 소모된 것으로 나타났습니다. 사용하다 보면 가끔씩 이상이 생기는 것은 당연합니다. 그래서 신속하게 Pod를 다시 시작하고 먼저 애플리케이션을 복원했습니다.
(7) 문제가 발견되었습니다. 다음으로 사용자 센터의 Pod가 끊긴 이유를 계속 조사하겠습니다. 다음 의심점부터 분석을 시작하세요:
(8) 의심점 계속 조사 a. 처음에는 Redis 링크를 얻을 수 없어 예외가 스레드 풀 큐에 들어가고 이후 큐 버스트가 발생하여 OOM이 발생한다고 생각했습니다. 이 아이디어에 따라 코드를 수정하고 업그레이드하고 계속해서 관찰했지만, 여전히 똑같은 느린 SQL과 사용자 센터 폭발이 발생했습니다. 이상이 없기 때문에 의심점 b도 배제할 수 있다.
(9) 현 시점에서는 비즈니스 A의 대형 테이블에 대한 전체 테이블 쿼리가 호출되는 지점인 c 지점이 의심되는 것이 거의 확실하며, 이로 인해 사용자 센터의 메모리가 너무 커지게 되고, JVM은 이를 재활용할 시간이 없으며 CPU를 직접 폭발시킵니다. 동시에 전체 테이블 데이터가 너무 크기 때문에 쿼리 중 메타데이터 잠금 시간이 너무 길어서 연결이 제때 해제되지 못하고 결국 거의 소진됩니다.
(10) 따라서 기업 A의 대규모 테이블을 쿼리하는 데 필요한 확인 조건을 수정하여 온라인 관찰을 위해 재배포했습니다. 최종 위치 선정에 문제가 있었습니다.
비즈니스 테이블 B를 변경할 때 MQ 메시지를 보내야 하기 때문입니다(비즈니스 테이블 A의 데이터를 ES로 동기화). MQ 메시지를 받은 후 비즈니스 테이블 A와 관련된 데이터를 쿼리한 후 해당 데이터를 Elasticsearch에 동기화합니다.
그런데 비즈니스 테이블 B를 변경할 때 비즈니스 테이블 A에 필요한 필수 조건이 전송되지 않았고, 필요 조건도 확인하지 않아 비즈니스 A의 대형 테이블에 대한 전체 테이블 스캔이 발생했습니다. 왜냐하면:
으아악당시 비즈니스 B 테이블의 빈번한 변경으로 인해 더 많은 MQ 메시지가 전송되고 소비되었으며, 이로 인해 비즈니스 A의 대규모 테이블에 대한 전체 테이블 스캔이 더 많이 트리거되었으며 결과적으로 MySQL 메타데이터 잠금 시간이 너무 길어졌습니다. 길고 최종 연결 수가 초과되었습니다.
동시에 A업체의 대형 테이블 쿼리 결과가 매번 사용자 센터의 메모리로 반환되어 JVM 가비지 수집이 실행되지만 결국 재활용할 수 없게 됩니다. .
Redis가 연결을 할 수 없다는 예외는 연막탄일 뿐입니다. MQ 이벤트가 너무 많이 전송되고 소비되기 때문에 소수의 스레드가 즉시 Redis 연결을 얻을 수 없습니다.
마지막으로 MQ 이벤트 소비를 위한 코드에 조건 확인을 추가하고 쿼리 비즈니스 A 테이블에도 필요한 조건 확인을 추가하고 온라인에 재배포하여 문제를 해결했습니다.
이 사건 이후 저는 몇 가지 교훈을 요약하여 여러분과 공유합니다.
(1) 온라인 문제에 항상 주의하고, 문제가 발생하면 방치하지 말고 신속하게 조사해야 합니다. 더 이상 네트워크 지터 문제를 의심하지 마세요. 대부분의 문제는 네트워크와 관련이 없습니다.
(2) 대규모 비즈니스 테이블 자체는 보호를 인식해야 하며 쿼리에는 필요한 조건 확인이 추가되어야 합니다.
(3) MQ 메시지를 사용할 때 필요한 조건을 확인해야 하며 정보 소스를 신뢰하지 마십시오.
(4) "이 조건은 반드시 전달될 것입니다. 반드시 가치가 있을 것이며, 반드시 비어 있지 않을 것입니다"라고 말하는 일부 동료를 절대 믿지 마십시오. 시스템의 높은 가용성과 안정성을 보장하기 위해 사람이 아닌 코드만 인식합니다.
(5) 문제 발생 시 일반적인 문제 해결 순서:
(6) 비즈니스 관찰 가능성과 경보는 필수적이며 포괄적이어야 합니다. 그래야 문제를 더 빨리 발견하고 해결할 수 있습니다.
위 내용은 시스템이 손상되었습니다. 코드만 인식하고 사람은 인식하지 못합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!