라벨이 sharding인 게시물 표시

2018년 15번째 주

이미지
이 포스팅은 그냥 지난 한 주간 읽었던 것들을 정리하는 포스트입니다. 그냥 예전에 봤던 글 중 나중에 필요한데 뭐였는지 기억 안 나는 글들이 있어서 쓰기 시작했습니다. 보통 하는 일과 관련된 글들이 올라오겠지만 딱히 정해둔 주제는 없고, 그때그때 관심 있었던 것을 읽었기 때문에 지난주에 쓰인 글일 수도 있고 몇 년 전에 쓰인 글일 수도 있습니다. 실제로 git 을 사용하면서 단순히 커맨드를 외워서 사용하는 사람들을 많이 봤다. 보통 그 이유로 크게 두 가지를 든다. 첫 번째로 git의 mental model 이 복잡하다는 것이다. git에서 변경된 내용은 크게 다음 상태 중 하나가 된다. 리모트에 존재하는 상태 로컬 브랜치에 있는 상태 브랜치에 머지되지 않았지만 add 돼 있는 상태 변경은 있지만 add 되지는 않은 상태 stash에 들어있는 상태 예전에 커밋했었지만 지금은 브랜치로 따라갈 수 없는 상태 이 중에서 내가 수정했던 내용이 어떤 상태인지 모르는 것이 헷갈리게 하는 첫 번째 이유다. 하지만 반대로 왜 이렇게 많은 상태를 가지게 됐을지 생각해보면 git을 사용하는 데 도움이 된다. 이것들은 전부 그냥 추가된 것이 아니다. 애초에 git을 처음 만든 사람은 Linus Torvalds 다. 그의 성격상 쓸모없는 것은 추가되지 않았다. 전부 제각각의 목적을 가지고 있다. 이 목적을 이해하는 것이 중요한데 아쉽게도 글로 잘 설명할 자신이 없다. 사실 이걸 이해하는 가장 빠르고 확실한 방법은 svn 을 써보는 것이다. 쓰다 보면 불편한 부분들이 자주 생기는데, git에서는 위에서 말한 것들을 이용해 이를 쉽고 빠르게 해결할 수 있다. 사람들이 git을 어려워하는 두 번째 이유는 명령어가 복잡하다는 것이다. 이건 어쩔 수 없다. 사실 git의 명령어는 규칙성 없이 만들어졌다. 그래서 외우는 수밖에 없다. 하지만 어떤 상황에서 어떤 명령어를 써야 한다는 식으로 외우면 끝이 없다. 그보다는 각 명령어가 어떤 상태와 연관이 있는지를 보는

이더리움 샤딩

현재 이더리움이 겪고 있는 가장 큰 문제는 scalability다. 이더리움이 인기를 끌면서 트랜잭션의 양도 늘어나고 참여하고 있는 노드의 수도 늘고 있는데 PoW를 쓰는 이더리움의 특성상 초당 트랜잭션 처리 수는 늘지 못한다. 그래서 지금 이더리움 코어 개발자들이 초점을 맞춰서 개발하고 있는 것이 ethereum sharding 이다. 이더리움 샤딩을 간단히 설명하면 샤드별로 merkle patricia tree 를 만들고 그 샤드의 root들로 만들어진 merkle partricia tree의 root만을 블록체인에 올리는 것이다. 이렇게 하면 모든 miner가 모든 트랜잭션을 실행할 필요 없이 각 샤드별로 miner를 분산시켜 실행할 수 있기 때문에 전체 실행 속도가 올라간다는 내용이다. 설명은 간단하지만 구현은 간단하지 않다. 이더리움은 replay attack 을 막기 위해서 account nonce라는 것을 도입했다. 현재 state에서 account가 가지는 nonce보다 1 큰 nonce를 가지는 트랜잭션만 유효한 transaction이기 때문에, 같은 account에서 보내는 2개 이상의 트랜잭션은 동시에 처리될 수 없다. 즉, 한 account의 트랜잭션이 두 개 이상의 샤드에서 실행되면 안전하지 못하다는 것이고, account는 샤드에 종속돼야 한다. 또한, 샤드는 독립적으로 실행돼야 한다. 이 말은 한 샤드에서 실행된 트랜잭션이 다른 샤드에 영향을 주지 못 한다는 것이고, 다른 샤드에 존재하는 account 사이에서는 트랜잭션을 주고받을 수 없다는 것이다. 현재 제안된 샤드 간 통신은 receipt tree를 이용하는 것이다. 예를 들어 shard N 의 account A 에서 shard M 의 account B 로 송금하는 상황을 생각해보자. 이때 N 은 account A 의 계좌를 차감하는 transaction T1 을 실행한다. T1 은 M 의 state를 변경할 수 없기 때문에 B 에게 바로 입금할 수 없다. 따라서 T1

[MongoDB] Sharding (3) - shard key

MongoDB는 auto sharding을 해주기 때문에 사용자가 어떤 shard에 저장할지 신경 쓰지 않아도 된다. 그렇다면 어떤 document를 어떤 shard에 저장할지 어떻게 결정할까? Shard Key MongoDB는 shard key를 이용하여 구분한다. 별도로 지정하지 않았다면 shard key는 object ID(_id)이다. 하지만 해당 collection에 모든 document에 존재하는 field index 혹은 compound field index라면 shard key로 지정할 수 있다. 하지만 compound index는 shard key로 지정할 수 없다. Shard key의 제약 조건 shard key에는 몇 가지 제약이 있다. 우선 shard key는 512 byte를 넘을 수 없다. 하지만 이는 시스템적 제약조건이지 실제로 512 byte를 넘는 field를 shard key로 만들 일은 거의 생기지 않는다. (사실 512 byte가 넘는 index를 지정하는 일도 거의 생기지 않는다.) 또한 한번 sharding한 collection에 shard key는 변경할 수 없다. 만약 변경하고 싶다면 새 collection을 만들어 shard key를 설정하고 collection 전체를 복사해서 새로운 collection을 만들어야 한다. 그다음 제약은 꽤 까다로운데 shard key로 지정된 field의 value는 변경할 수 없다. Update 때 document를 다른 shard로 옮겨야 할 일이 없도록 하기 위해서다. 변경할 일 없는 field들만을 shard key로 지정해야 한다. 특별히 튜닝해야 할 일이 없다면 기본값인 object id를 shard key로 사용하는 것을 추천한다.

[MongoDB] Sharding (2) - Primary shard

MongoDB는 collection 별로 sharding을 할지 안 할지를 결정할 수 있다. 이때 sharding되지 않은 collection들이 저장되는 shard를 "Primary Shard"라고 부른다. sharding되지 않은 data들이 들어 있기 때문에 이는 Single point of failure 이다. 혹시 primary shard인 머신을 down시켜야 한다면 movePrimary command로 다른 shard를 primary로 만들고 down시켜야 한다. movePrimary는 sharding되지 않은 collection들을 모두 copy해가기 때문에 무거운 작업이다. 될 수 있으면 movePrimary를 호출할 상황이 오지 않도록 노력해야 한다. 별도로 primary shard를 정하지 않았다면, 가장 먼저 cluster에 붙은 shard가 primary shard가 된다. p.s. 솔직히 말하면 난 아직 primary shard를 사용해야 하는 경우를 보지 못했다. 아마 내 MongoDB 튜닝 경험이 적어서 그럴 것이다. 혹시 primary shard를 이용해야 했던 경험이 있다면 공유해주기 바란다.

[MongoDB] Sharding (1) - Sharded cluster의 구성

Scale up과 Scale out 한 머신이 처리하지 못할 정도로 부하가 들어왔을 때의 해결책을 크게 scale up과 scale out 두가지로 분류한다. Scale up은 머신 자체의 성능을 올리는 것으로 vertical scaling이라고 불린다. 효과는 확실하지만, scale out보다 비용이 많이 든다. Scale out은 기존의 머신을 그대로 두고 새로운 머신을 추가하는 방식이다. 다른 말로는 horizontal scaling이라고 부른다. Sharding 은 scale out의 일종으로 data를 여러 서버에 나눠서 저장하는 방식을 말한다. 이때 data가 저장된 서버들을 shard라고 부르고 shard들을 포함한 몽고디비 환경을 sharded cluster라고 부른다. Sharded cluster MongoDB의 sharded cluster는 크게 3가지 군으로 나뉜다. Shards Config Servers Query Routers Shard Shard 는 실제 data가 저장되는 곳이다. MongoDB는 보통 하나의 data를 세 군데의 shard에 저장하여 특정 shard가 Single point of failure(a.k.a. SPOF) 가 되는 것을 막는다. Scaling을 위해 수를 줄이고 늘리고 하는 것이 이 shard이다. Config Server Config server 에는 shard된 data들의 metadata. 즉, 어떤 data가 어떤 shard들에 저장되어 있는지에 관한 정보가 저장되어 있다. 하나의 Config server만을 이용할 수도 있지만 보통 3개의 Config server를 사용하여 특정 Config server가 SPOF가 되는 것을 막는다. Config server에 저장되는 정보는 two-phase commit으로 저장하여 consistency를 보장해준다. Config server는 shard와 달리 scaling의 대상이 아니다. 보통 3개의 Config Ser

이 블로그의 인기 게시물

[C++] enum class - 안전하고 쓰기 쉬운 enum

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

RAII는 무엇인가

[Python] cache 데코레이터로 최적화하기

[Web] SpeechSynthesis - TTS API