분포식 시스템 - 실험 - kvraft

3217 단어

소개


이번에 우리는 실험2: Raft를 바탕으로 오류를 수용할 수 있는 키 값 저장 서비스를 만들어야 한다.구체적으로 말하면 몇 개의 Raft 실례를 이용하여 오류를 수용할 수 있는 상태기를 구성하고 서로 다른 클라이언트 조작은 Raftlog를 통해 일치성을 확보한다.또한 절반 이상의 Raft 인스턴스가 정상적으로 작동하고 상호 통신이 가능한 경우 서비스가 올바르게 실행됩니다.
kvraft 패키지에서 우리는 Key/Value의 서버와 클라이언트를 실현해야 한다. 물론 서버는 하나의 Raft 실례이다.클라이언트는 서버에 Put(), Append() 및 Get() RPC를 전송할 수 있으며, 서버는 이 명령을 로그에 넣고 순서대로 실행합니다.클라이언트는 모든 서버에 요청을 보낼 수 있지만, 방문한 서버가leader가 아니거나 응답이 없으면 서버를 바꿔야 합니다.만약에 클라이언트 명령이 로그에 기록된 것을 확정한다면 클라이언트에게 말해야 한다. 만약에 서버가 다운되거나 네트워크가 고장나면 클라이언트는 같은 명령을 다른 서버에 보내야 한다.
우리의 실험은 두 단계로 나뉜다. 첫 번째 단계는 모든 요청 내용을 로그 목록에 간단하게 추가하고, 그의 공간 점용을 고려하지 않는다.두 번째 단계는 논문 7장의 내용을 실현하고 snapshot으로 쓸모없는log를 회수합니다.
비록 이 실험은 많은 코드를 쓰지 않지만, 당신의 실현이 왜 안 되는지 이해하는 데 시간이 오래 걸릴 것이다.사실 실험2보다 debug가 더 어렵다. 왜냐하면 더 많은 모듈이 비동기적인 작업 방식이기 때문이다.
본 실험의 코드는 src/kvraft에 있어야 합니다.go에서 실현됩니다.모든 테스트를 통과해야 합니다.
$ setup ggo_v1.5
$ cd ~/6.824
$ git pull
...
$ cd src/kvraft
$ GOPATH=~/6.824
$ export GOPATH
$ go test
...
$

Step 1: 초기 Key/Value 구현


우선 우리의 서비스 대외 인터페이스를 명확히 하자.
  • Put(key, value),key에 새 값value
  • 설정
  • Get(key), 키의 값 얻기
  • Append(key, arg), 키의 값에 추가arg
  • Dell 서비스는 여러 Raft 인스턴스로 백업 상태 클러스터를 구성하므로 클라이언트가 다른 서버와 통신을 시도해야 합니다.리더가 연결되어 있고 절반 이상의 기계가 정상적으로 작동하면 클라이언트의 명령이 실행되어야 합니다.
    물론 우리는 먼저 가장 간단한 장면, 즉 기계 고장이 없다는 것을 실현했다.그러나 우리는 서비스 응답의 순서 일치성을 확보해야 한다.즉, 클라이언트의 명령은 각 Raft 인스턴스에서 동일한 순서로 실행되고 각 명령은 최대 한 번 실행됩니다.Get(key)은 최신 데이터를 읽어야 합니다.
    먼저 Opstruct에 어떤 속성이 부족한지 보고 PutAppend () 와 Get () 의 Handler를 실현합니다. 이것은 Raft의 Start () 방법을 사용해서 Op를 로그에 넣고 Raft가 applyCh에 데이터를 보내서 방금 명령이 성공적으로 실행되었음을 표시해야 합니다. 그 전에 Start () 에 새로운 명령을 보내지 말아야 합니다.성공 메시지를 받은 후 클라이언트에게 피드백을 합니다.
    완료되면 "One client"테스트를 통과해야 합니다.
    우리가 Start () 를 보내고 결과를 얻는 것은 비동기적이기 때문에 선후 관계를 어떻게 처리해야 하는지를 고려해야 한다.
    리더가 Start () 명령을 받았지만commit 전에 리더 신분을 잃었을 때 클라이언트는 새 리더를 찾아 이 명령을 다시 보내야 합니다.클라이언트가 연결된 리더가 네트워크에서 격리되었을 때 이 리더는 자신이leader라고 생각하고 시스템에서 명령을 실행할 수 없을 뿐만 아니라 클라이언트도 새로운 리더가 있는지 모른다. 이런 상황에서 클라이언트는 무한히 기다릴 수밖에 없다.
    가장 좋은 것은 지난번 리더의 index를 기억하는 것이다. 그러면 리더가 아닌 리더를 찾는 시간을 줄일 수 있다.
    네트워크와 Raft 실례가 항상 안정적이지 않다고 가정하기 때문에, 같은 요청이 한 번만 처리될 수 있도록 요청을 여러 번 보내는 상황을 처리해야 합니다.그래서 우리는 다른 요청을 표시하기 위해 추가 데이터가 필요하다.
    같은 요청이 다시 실행되는 상황을 처리합니다. 클라이언트가term1에서leader1에 요청을 보내고 응답이 초과될 때까지 기다린 후에 이 요청을leader2에 보냈습니다. 이때term2에 있습니다.클라이언트의 요청은 한 번만 실행되어야 합니다.Step 1을 완료하면 이전 테스트를 모두 통과해야 합니다.
    하나의 요청은 서버에 한 번만 실행될 수 있다. 이것은 클라이언트가 서로 다른 요청을 어떻게 식별하는지에 달려 있다. 모든 요청에 표시 위치를 추가할 수 있다. 물론 모든 클라이언트가 동시에 하나의 요청만 처리할 수 있도록 규정할 수도 있다.

    Step 2: 압축 로그 이중화 감소


    Raft의log가 무제한으로 증가하기 위해서, 우리는 스냅샷(snapshot, 논문 7장) 메커니즘으로 정기적으로 쓸모없는 log를 삭제할 수 있어야 한다.TestPersistPartitionUnreliable() 전송된 매개변수StartKVServer()는 각 Raft 인스턴스가 log를 저장하는 데 사용되는 공간 크기를 나타냅니다.공간이 부족할 때마다 snapshot을 생성하고 Raft의 현재 로그가 디스크에 스냅샷으로 저장되어 있음을 알려 줍니다. maxraftstate 메모리의 로그를 버릴 수 있습니다.
    snapshot 메커니즘을 실현하려면raft 패키지의 코드를 수정해야 합니다.follower가 필요로 하는 동기화 로그가 디스크에 스냅샷으로 저장되었을 때,leader는follower에 persister.SaveSnapshot() RPC를 보내야 합니다.follower가 이런 RPC를 받은 후,kvraft에 대응하는 snapshot를 보내야 합니다.
    snapshot은 로그 목록뿐만 아니라 요청 시퀀스 번호 등 관련 정보를 저장해야 합니다.

    좋은 웹페이지 즐겨찾기