Postgres에 스트라이프를 동기화하는 방법

Sync Corporation에서는 API를 Postgres 데이터베이스로 실시간으로 복제합니다.우리는 고객에게 제3자 플랫폼(예를 들어 Stripe와 Airtable)에서 직접 자신의 데이터를 방문하는 체험을 제공하기를 희망한다.
Stripe의 API는 매우 훌륭하기 때문에, 우리는 우리의 Stripe 지원이 첫날에 반드시 매우 빠르고 믿을 만해야 한다는 것을 안다.API 읽기를 대체하기 위해서, 우리의 동기화는 진정으로 두 번째 진실의 원천이 되는 데이터베이스를 만들어야 한다.즉,

  • 모든 데이터를 다시 채워야 합니다. 처음 동기화할 때, 지정한 테이프 계정의 모든 역사 데이터를 목표Postgres 데이터베이스에 불러옵니다.

  • 가상 대상 지원: Stripe에는'가상'대상이 있습니다. 예를 들어'곧 발표될 영수증'이러한 객체는 작성되기 전까지 변경된 상태입니다(예: 청구서가 발행될 경우).너는 그것들을 한 번에 되찾아야 한다. 왜냐하면 그것들에게 페이지를 나누어 줄 곳이 없기 때문이다.그들은 심지어 메인 키조차 없다.

  • 우리는 a/wait 노드를 제공합니다. 보시다시피, 고객은 Stripe 변경 사항을 쓴 후에 Sync Inc에서 /wait 노드를 호출할 수 있습니다.우리가 데이터베이스가 완전히 최신이라는 것을 확인했을 때, 이 단점은 하나 200 로 되돌아갈 것이다.즉, Stripe에 기록된 후 데이터베이스를 읽고 일관성을 알 수 있습니다.

  • 두 가지 주요 동기화 전략
    우리의 테이프는 테이프의 events 단점을 둘러싸고 동기화됩니다.이 단점의 용도는 데이터베이스에 있는 복제 슬롯과 같다.해당 계정에서 발생한 모든 생성/업데이트/삭제 이벤트 목록이 스트라이프에 포함되어 있습니다.
    모든 이벤트는 영향을 받은 기록의 완전한 유효 부하를 포함한다.이 이벤트 흐름을 사용하면 테이프 계정에 대한 모든 변경 사항을 효과적으로 재생할 수 있습니다.
    그러나 예상한 바와 같이, 단점은 하나의 테이프 계정에 있는 모든 사건의 무한 목록을 포함하지 않습니다.그것은 지난 30일의 데이터를 포함한다.
    따라서 고객이 새로운 복사본인 Postgres 데이터베이스를 시작할 때, 우리는 먼저 역사 테이프 데이터로 메워야 한다는 것을 의미한다.메모는 단지 모든 단점을 페이지로 나누어 계정의 시작을 메모하는 것을 의미할 뿐이다.
    우리는 마침내 두 가지 다른 동기화 과정을 얻었다. 그것이 바로 메우기 과정과 이벤트 윤문 과정이다.
    우리는 우선 메우기 과정을 실행해서 초기 데이터베이스를 구축한다.그런 다음 데이터베이스의 수명 주기 동안 이벤트 폴링 프로세스를 계속해서 실행하여 동기화를 유지합니다.

    동기화 프로세스:메우기
    메우기 과정에서, 우리는 테이프에 있는 모든 단점의 완전한 역사를 페이지로 나누어야 한다.
    Stripe API의 폭을 고려하면 메우기가 다음과 같은 과제를 안고 있습니다.
  • 수십 개의 API 엔드포인트에 요청해야 합니다.
  • 그리고 모든 단점에 대해 우리는 JSON 응답을 Postgres에 삽입할 수 있는 구조로 전환해야 한다.
  • 또한 각 응답에는 다중 중첩 하위 레벨이 포함될 수 있습니다.이 하위 항목들은 하위 항목의 목록일 수도 있고, 이 하위 항목들은 페이지를 나눌 수도 있다.
  • 이것은 불로장생약Broadway을 사용하는 절호의 핑계다.브로드웨이 파이프는 프로듀서 한 명과 노동자 한 명 혹은 여러 명으로 구성되어 있다.프로듀서는 일자리 창출을 책임진다.노동자들은 이 일들을 소모하고 일하는데, 모든 일은 평행이다.브로드웨이는 우리에게 상자를 열면 바로 쓸 수 있는 물건을 주었다.
  • 압력을 등진 노동자 대열이 있다.
  • 우리는 해야 할 작업량에 따라 파이프의 노동자 수를 동태적으로 조정할 수 있다.
  • 우리는 단위 시간 내에 처리하는 작업량을 쉽게 등급별로 제한할 수 있다.Stripe의 API 할당량 제한보다 훨씬 낮게 조정했습니다.
  • 확인/실패 행위를 가진'메시지'구조.이것은 논리를 다시 시도하는 이런 일을 보잘것없게 만들었다.
  • 우리의 예에서 생산자가 유지하는 작업 대기열은 처리할 페이지 목록입니다.페이지는 끝점과 현재 커서의 조합입니다.다음은 작은 예입니다.
    queue = [
      {"/v1/customers", "cur9sjkxi1x"},
      {"/v1/invoices", "cur0pskoxiq1"},
      # ...
    ]
    
    
    처리량을 구성하려면 브로드웨이 인스턴스화를 위해
    options = [
      producer: [
        module: BackfillProducer,
        rate_limiting: [
          allowed_messages: 50,
          interval: :timer.seconds(1)
        ]
      ],
      processors: [
        default: [
          concurrency: 50,
          max_demand: 1
        ]
      ]
    ]
    
    
    rate_limiting 설정은 우리가 초당 50페이지를 넘지 않도록 하는 데 필요한 것이다.이렇게 하면 고객의 스트라이프 할당량 중 초당 50개의 요청만 남는다.processors항에서 우리는 최대 50명의 아르바이트 노동자를 필요로 하고 한 사람이 매번 하나의 업무 단원을 요구할 수 있도록 지정했다(우리의 예에서 한 페이지).
    따라서 동기화를 가동하기 위해 생산자의 대열을 메우기 위해 모든 밴드 단점(과nil 커서)을 파종했다.우리 직원들은 한 페이지의 업무를 결산하고 그것을 얻었다.각 페이지에는 최대 100개의 객체가 포함됩니다.모든 대상은 페이지를 나눌 수 있는 하위 대상의 목록을 포함할 수 있다.따라서 작업자의 첫 번째 작업은 페이지의 모든 대상을 완전히 채우는 것이다.
    일단 '채우기' 대상의 목록이 생기면, 우리는 그것들을 분석하고 삽입할 것이다.객체 유형과 필드를 Postgres의 테이블과 열에 매핑하는 대형 JSON 객체를 사용합니다.우리는 모든 테이프 대상에 object 필드가 포함되어 있다는 사실에서 이득을 보았는데 이 필드는 실체가 무엇인지를 표시한다.

    동기화 프로세스:새 이벤트
    메모가 완료되면 동기화된 무한 생존 기간 내에 사건 처리로 전환할 때가 되었다.그러나 우리는 둘 사이의 순조로운 교차가 필요하다. 그렇지 않으면 우리는 변화를 놓칠 수도 있다.
    인계를 편리하게 하기 위해서, 메모를 시작하기 전에, 우리는 /events 에 가장 가까운 커서를 가져오도록 요청합니다.메모가 끝난 후, 우리는 먼저 메모 기간에 발생한 모든 사건을 이해한다.이 데이터를 처리한 후 데이터베이스는 최신이다.지금은 무기한 투표/events할 때다.
    우리는 500밀리초 간격으로 /events 단점에 대해 윤문을 해서 새로운 내용이 지속적으로 처리되어야 하는지 확인한다.이것이 바로 우리가 어떻게 아초의 지연을 보장하는 방법이다.
    Postgres 테이블에 기록이 동기화됩니다.우리는 '멀티태스킹 삽입' 모드를 사용합니다. 그 중에서 로그 항목마다 JSONpayload을 포함하고 몇 가지 형태 중 하나를 사용할 수 있습니다.예를 들어, 막대 반입 완료 로그는 다음과 같습니다.
    {
      "kind": "stripe_backfill_complete",
      "row_count": 1830,
      "last_event_before_backfill": "evt_1J286oDXGuvRIWUJKfUqKpsJ"
    }
    
    테이프 동기화 프로세스를 시작할 때,synclogs표를 검사하고, 이 데이터베이스가 최근에 완성한 동기화를 볼 것입니다.그리고 동기화 관리자는 어떤 동기화 프로세스를 시작해야 하는지, 그리고 이 프로세스의 초기 상태를 알고 있습니다.

    인터넷 갈고리는요?
    사람들이'실시간'또는'사건'API 통합을 들었을 때 가장 먼저 떠오르는 API 원어는 바로'webhooks'이다.
    그러나 웹훅스는 다음과 같은 도전을 가져왔다.

  • 아래로 내려갈 수 없습니다. 발송자는 보통 지수급이 되돌아오는 상황에서 미송달된 웹훅을 다시 시도합니다.그러나 이런 보증은 종종 느슨하거나 명확하지 않다.재난에서 복구된 후, 시스템이 가장 필요로 하지 않을 수도 있는 것은 대량의 백업을 처리하는 웹훅입니다.

  • 당신이 바라는 것은 발송자의 교부성이다. 윤문할 때, 당신과 최신 데이터 사이의 유일한 진정한 장애는 가능한 캐시층이다.Webhook이 있으면 발송자는 보통 어떤 대기열이나 '발송함' 을 가지고 직원들이 사용하도록 제공한다.이와 같은 대열은 배압의 영향을 받을 것이다.발송자의 대기열 백업을 하면 동기화 속도가 느려집니다.

  • 불필요한 시스템: Webhook은 우리가 유일하게 의존할 수 있는 동기화 작업이 아니기 때문에 항상 퀴즈 시스템으로 보충해야 한다.우리는 데이터베이스를 초기화한 후에 데이터베이스를 메우기 위해 윤문해야 한다.웹 훅 처리 논리의 오류를 복구하거나 복구한 후에 투표를 해야 할 수도 있습니다.
  • 전반적으로 말하자면, 나는 순전히 웹훅에 의존해서 동기화를 유지하는 시스템이 반드시 실패할 것이라고 의심한다.수신자나 송신자에서 웹훅을 버리면 됩니다.다른 백업 메커니즘이 없으면 데이터베이스에 있는 기록이 기한 없이 동기화되지 않을 수도 있습니다.
    다행히도 /events 단점을 사용하여 윤문할 때 웹훅이 필요하지 않다는 사실이 증명되었다.비결은 투표를 충분히 빈번하게 하면 가능한 한 실시간에 접근할 수 있다는 것이다!가장 좋은 것은 같은 동기화 시스템을 사용하여 밀리초 전의 변경 사항을 가져오거나 의외의 정지 기간에 발생한 모든 변경 사항을 추적할 수 있다는 것이다.

    대기 끝
    우리의 데이터베이스는 읽기만 한다.고객은 플랫폼의 인증 스택을 통해 이러한 쓰기 작업을 수행할 수 있도록 플랫폼의 API에 대해 쓰기 작업을 수행합니다.그리고 이 변경 사항들은 그들의 데이터베이스에 흐른다.전화번호one-way data flow we advocate입니다.
    우리의 Stripe 데이터베이스가 진정한 두 번째 진실의 원천이 되기 위해서는 마지막 지주가 필요하다."먼저 읽고 나중에 쓰기"를 사용하거나, Stripe의 API에 대해 쓰기 작업을 하면 다음 읽기에 데이터베이스에 반영될 수 있도록 보장해야 합니다.Dell의 스트라이프 동기화는 매우 빠르지만 현재의 아키텍처는 스트라이프에 쓰기를 수행한 후 전파를 변경하기 전에 데이터베이스를 조회할 수 있는 경쟁 조건을 두고 있습니다.
    이런 경쟁 상황을 극복하는 가장 간단한 방법은 어떤 후속 읽기가 시작되기 전에 1초 동안 잠을 자는 것이다.이것은 줄곧 효과가 있을 것이다.하지만 우리는 더 강한 것을 제공하고 싶다.
    "고객은""대기""엔드포인트를 호출할 수 있습니다."
    GET <https://api.syncinc.so/api/stripe/wait/:id>
    
    스트라이프 데이터베이스가 최신인지 확인할 때까지 이 노드는 열려 있습니다.해당하는 경우 요청이 200로 반환됩니다.이제 데이터베이스에 대한 후속 읽기를 안심할 수 있습니다.

    임박
    메모, '곧 다가올 영수증' 등 가상 대상에 대한 지원, 초당 이하의 동기화 시간을 통해, 우리는 귀하께 모든 테이프 데이터를 포함하는 진정한 Postgres 사본을 제공합니다.
    개발자들이 이 데이터베이스의 위대함을 체험할 수 있도록 우리는 여전히 해야 할 일이 많다.82개의 탁자가 있어 어지럽고 현기증이 난다(!!)많은 개발자들에게 강력한 ORM 지원은 필수적이다.현재 동기화의 기초가 마련되었으니 전체적인 체험의 업데이트에 계속 관심을 가져 주십시오.

    좋은 웹페이지 즐겨찾기