LabHub
学习 学习路径 课程

数据流水线

把隔离运营起来 — 堆积、熔断、重投

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

기대치를 파일로 적어 두고, 드롭을 실행마다 줄 단위로 걸러 sqlite 의 사실 표와 격리 표로 나눠 쌓는 문지기 qgate.py 를 만든다. 너무 많이 틀린 실행은 통째로 끊고, 고친 줄을 다시 넣되 이중 계산이 안 나게 하고, 나이 든 격리를 잡아내고, 실행 상태와 자료 상태를 갈라 보고한다.

왜 중요한가

못 쓰는 줄을 버리지 않고 격리에 남기는 것까지는 대개 한다. 문제는 그다음이다. 격리는 실행마다 다시 쌓이고, 반년 뒤에 열어 보면 4만 줄이 들어 있고, 그동안 집계는 그만큼 빠진 채로 나가고 있었다. 파이프라인은 매일 성공했다 — 성공은 오류 없이 끝났다는 뜻이지 넣어야 할 것을 다 넣었다는 뜻이 아니다. 줄 하나가 틀린 것과 파일 전체가 틀린 것도 다른 사건이다. 상류가 칼럼 순서를 바꿔 보내면 거의 모든 줄이 어긋나는데, 그때 줄 단위로 격리하면 격리 표에 만 줄이 들어가고 집계는 빈 채로 나간다. 그런 파일은 한 줄도 넣지 않고 실행을 끊는 편이 낫다. 가르는 기준은 비율이고, 그 비율은 둥근 수가 아니라 평소 실패 비율에서 정한다. 그리고 고친 줄을 다시 넣는 고리가 필요하다. 재투입은 사람이 손으로 돌리는 일이라 반드시 여러 번 실행되고, 그때 사실 표에 두 번 들어가거나 이미 닫힌 격리를 또 닫아 "3건 해결" 이 두 번 보고되기 쉽다. 채점기는 여러분이 적어 낸 문구를 믿지 않는다. 임시 디렉터리에 채점기가 만든 드롭과 기대치를 차려 놓고 여러분의 문지기를 실제로 실행한 뒤, 만들어진 sqlite 파일을 직접 열어 사실과 격리와 실행 기록을 채점기가 직접 센 값과 대조한다. 임계치와 상호와 금액은 실행마다 바뀐다.

단계

  1. /root/quarantine/gen_drops.py 를 만들어 실행해 /root/quarantine/drops 아래 드롭 넷과 /root/quarantine/expectations.json 을 만드세요.
  2. /root/quarantine/qgate.pycheck 를 만들어 기대치로 세어만 보게 하세요.
  3. run 을 더해 sqlite 에 사실과 격리와 실행 기록을 쌓게 하세요.
  4. run --max-fail-ratio 를 더해 너무 많이 틀린 실행을 통째로 끊게 하세요.
  5. requeue 를 더해 고친 줄을 다시 넣되 두 번 넣어도 숫자가 안 변하게 하세요.
  6. aging 을 더해 나이 든 격리를 잡아내게 하세요.
  7. status 를 더해 실행 상태와 자료 상태를 갈라 보고하게 하세요.
  8. 자기 드롭 넷을 차례로 돌려 /root/quarantine/pipeline.db 를 만들고 /root/quarantine/status.json/root/quarantine/quarantine_report.md 를 쓰세요.

참고

드롭과 기대치를 파일로 두기

/root/quarantine/gen_drops.py 를 만들어 실행해 /root/quarantine/drops 아래 드롭 넷과 /root/quarantine/expectations.json 을 만드세요. 기대치는 다섯 가지 type 을 모두 쓰고, 드롭 하나는 절반이 넘게 기대치를 어겨야 합니다.

기대치를 코드가 아니라 파일로 두면 상류와 그 파일을 놓고 이야기할 수 있고, 어긴 규칙의 이름이 그대로 격리 사유가 됩니다. 드롭에는 상태값이 목록에 없는 줄, 음수 금액, 범위를 넘는 수량, 빈 상호, 규격을 안 지킨 전표 번호, 앞줄과 같은 전표 번호를 섞으세요. 셋은 어기는 줄이 절반 아래여야 하고 하나는 절반을 넘어야 합니다.

기대치로 세어만 보기

/root/quarantine/qgate.pycheck --drop <파일> --expect <파일> 을 만들어 drop·rows·passed·failed·fail_ratio·by_rule 을 JSON 으로 내게 하세요.

failed 는 한 규칙 이상을 어긴 줄의 수이고 by_rule 은 규칙마다 어긴 줄의 수라 합이 다릅니다 — 한 줄이 두 규칙을 어길 수 있기 때문입니다. by_rule 에는 아무도 안 어긴 규칙도 0 으로 넣으세요. 값이 비어 있으면 not_null 말고는 전부 실패로 봅니다.

사실과 격리를 나눠 쌓기

run --drop <파일> --db <파일> --expect <파일> 을 더해 통과한 줄은 facts 에 갱신으로 넣고, 어긴 줄은 어긴 규칙마다 quarantine 에 열고, 실행을 runs 에 남기게 하세요. 같은 줄의 같은 사유가 다시 와도 격리는 한 번만 엽니다.

표 셋의 칼럼 이름과 순서는 참고 절에 있습니다. 사실 표는 order_id 가 기본 키이므로 갱신으로 넣습니다. 격리를 열기 전에 같은 order_id 와 rule 로 아직 열려 있는 줄이 있는지 보세요 — 안 보면 실행마다 같은 줄이 쌓입니다.

너무 많이 틀린 실행은 통째로 끊기

run --max-fail-ratio R 을 더해 fail_ratio 가 임계치를 넘으면 실행을 끊게 하세요. 끊긴 실행은 runsbroken 으로 남기고 사실도 격리도 한 줄도 넣지 않으며 종료 코드 5 입니다.

줄 하나가 틀린 것과 파일 전체가 틀린 것은 다른 사건입니다. 임계치는 둥근 수가 아니라 평소 실패 비율에서 정합니다 — check 로 드롭 넷의 비율을 재어 보고 정하세요. 끊을 때 절반만 넣고 멈추면 다음 사람이 어디까지 들어갔는지 판단해야 합니다.

고친 줄을 다시 넣기

requeue --db <파일> --fixes <파일> --expect <파일> 을 더해 고친 줄을 기대치로 다시 보고, 통과하면 사실 표에 갱신으로 넣고 그 전표의 아직 열려 있는 격리만 닫게 하세요. 같은 재투입을 두 번 실행해도 사실 건수와 닫힌 격리 수가 늘지 않아야 합니다.

재투입은 사람이 손으로 돌리는 일이라 반드시 여러 번 실행됩니다. 삽입으로 넣으면 사실이 두 배가 되고, 닫을 때 열림 조건을 안 걸면 '3건 해결' 이 두 번 보고됩니다. 두 번째 실행의 resolved 는 0 이어야 합니다. 전표 번호 자체가 망가진 줄은 재투입으로 못 고칩니다 — 번호를 고치면 다른 줄이 되기 때문입니다.

나이 든 격리를 잡아내기

aging --db <파일> [--max-age-runs N] 을 더해 열려 있는 격리의 나이를 latest_run_id - first_run_id 로 재고, max_age_runs 이상인 것을 세어 open·aged·by_rule·oldest·alert 로 내게 하세요.

건수만 보면 안 줄어드는 것을 못 봅니다. 나이는 시각보다 실행 횟수로 재는 편이 다루기 쉽습니다 — 파이프라인이 안 돌면 나이도 안 먹는 편이 사람의 감각과 맞습니다. oldest 는 열려 있는 것 중 first_run_id 가 가장 작은 것입니다.

성공했다와 맞다를 갈라 보고하기

status --db <파일> [--max-age-runs N] 을 더해 실행 상태(runs)와 자료 상태(data)를 갈라 내고 runs_ok·data_ok 두 값으로 답하게 하세요.

실행이 성공했다는 것과 자료가 맞다는 것은 다른 축입니다. 한 칸에 뭉치면 둘 다 못 봅니다. runs_ok 는 실행이 있고 마지막 실행이 끊기지 않았는가이고, data_ok 는 열린 격리와 나이 든 격리가 모두 0 인가입니다 — 둘 다 참인 날은 드뭅니다.

자기 드롭으로 한 주를 돌리고 보고하기

자기 드롭 넷을 날짜순으로 돌려 /root/quarantine/pipeline.db 를 만들고, status 의 답을 /root/quarantine/status.json 에 남기고, /root/quarantine/quarantine_report.md 를 네 절로 쓰세요. 중단 임계치는 평소 실패 비율을 재어 정하세요.

임계치를 평소 값에서 정하면 절반이 넘게 어긴 그날치만 끊깁니다. status.json 은 손으로 쓰지 말고 status 명령의 답을 그대로 저장하세요 — 채점기는 데이터베이스를 직접 열어 대조합니다. 보고서에는 사실 건수와 열린 격리 건수를 숫자로 적으세요.