Timestamps in Message-Passing Systems That Preserve the Partial Ordering

Fidge, C.J., Timestamps in Message-Passing Systems that Preserve the Partial Ordering, Proc. 11th Australian Comp. Sci. Conf., 1988, pp. 56-66.

Timestamping is a common method of totally ordering events in concurrent programs. However, for applications requiring access to the global state, a total ordering is inappropriate. This paper presents algorithms for timestamping events in both synchronous and asynchronous message-passing programs that allow for access to the partial ordering inherent in a parallel system. The algorithms do not change the communication graph or require a central timestamp issuing authority.

이 논문은 Vector Clock으로 알려진 개념을 소개하고 있다. Vector Clock은 [Fidge 1998]과 [Mattern 1998]에서 독립적으로 고안된 알고리즘인데, Fidge의 논문쪽이 좀 더 읽기 쉬운 편이라고 한다.

Limitation of Lamport’s logical clock

Clock Condition. For any events a, b:
if a → b then C(a) < C(b).

Lamport가 정의한 논리적 시계는 두 사건 사이의 happened-before 관계가 있다면 이를 반영하는 시계를 정의하고 있습니다. 그리고 이를 이용해 임의의 완전순서를 정의하고 있습니다. 이 완전순서는 임의의 프로세스 사이의 순서를 이용하고 있으므로 사건들을 정렬할 수 있는 방법 중의 임의적인 한 방법이고, 논리적 시계 이상의 어떤 정보가 추가되지는 않습니다.

Lamport가 정의한 논리적 시계의 문제는 이 논리적 시계를 통해서 사건들 사이의 인과성 (causality)를 알아낼 수 없다는 것입니다. 즉, C(a) < C(b)라고 해서 a  b라고 말할 수 없는 것입니다. 구체적으로 말해, C(a) < C(b)가 의미할 수 있는 것은 a와 b 사이에 happend-before 관계가 있는 것, 즉  a  b인 경우와, a와 b 사이에 happend-before 관계를 판단할 수 없고 b가 a에 대해 happened-before가 아닌 것, 즉 b ↛ a인 경우가 있습니다.

Vector Clock

Vector Clock이라는 단어를 논문에서 사용하고 있지는 않지만, 그 단어가 의미하듯이 논리적 시계의 타임스탬프를 integer가 아니라 다음과 같이 프로세스 수 만큼의 타임스탬프를 가진 배열로 대체하고 있습니다.

[c1, c2 … cn]

그리고 이 타임스탬프를 유지하기 위한 알고리즘은 아래와 같습니다. 타임스탬프가 배열이 되었다는 것 이외에 Lamport의 알고리즘과 큰 차이가 없다고도 얘기할 수 있겠지만, 주의를 기울여야 하는 부분은 메시지를 수신하는 프로세스에서는 메시지를 송신한 프로세스에 해당하는 타임스탬프 배열 항목의 값만을 증가시킨다는 것입니다.

Rule RA 1: Initially all values are zero.

Rule RA 2: The local clock value is incremented at least once before each atomic event

Rule RA 3: The current value of entire timestamp array is piggybacked on every outgoing signal

Rule RA 4: Upon receiving a signal, a process sets the value of each entry in the timestamp array to be the maximum of the two corresponding values in the local array, and in the piggybacked array received. The value corresponding to the sender, however, is a special case and is set to be one greater than the value received (to allow for transit time), but only if the local value is not already greater than that received (to allow for signal “overtaking” as described below), i.e.

q?other_array; /* receive timestamp array from process q */
if local_array[q] <= other_array[q] then
    local_array[q] := 1 + other_array[q];
for i := 1 to n do
    local_array[i] := max(local_array[i], other_array[i]);

Rule RA 5: Values in the timestamp arrays are never decremented.

이 논문에서는 설명하고 있지 않지만, 이러한 알고리즘으로 얻어지는 타임스탬프의 의미는 수신한 메시지에 근거해서 추측할 수 있는 가장 정확한 송신 측의 타임스탬프라는 것입니다. 또한, 수신한 프로세스에서 발생할 현재의 사건에 대해 happened-before 관계에 있는 송신 측의 프로세스의 가장 마지막 사건의 타임스탬프이기도 합니다.

이러한 타임스탬프 배열은 다음과 같이 비교될 수 있습니다.

각각 프로세스 p, q에서 실행된 사건 e, f를 ep, fq로 나타내고, 각 사건에 대한 타임스탬프 array를 Tep, Tfq, 그 타임스탬프 배열 중 프로세스 p에 해당하는 타임스탬프를 Tep[p], Tfq[p] 라고 할 때,

ep → fq iff Tep[p] < Tfq[p]

여기서 주목할 점은 iff 즉, 사건의 happened-before 관계와 타임스탬프의 대소 관계가 동치관계라는 것입니다. 임의의 두 사건이 주어졌을 때 인과성이 있는지 여부와 어떤 사건이 어떤 사건에 대해 인과성이 있는지를 판단할 수 있습니다.

ep ↔ fq if Tep[p] ≮ Tfq[p] and Tfq[p] ≮ Tep[p]

타임스탬프 사이의 대소 관계가 어느 방향으로도 성립하지 않는다면 두 사건은 동시적(concurrent)하다고 얘기할 수 있습니다.

Applications

그렇다면 논리적 시계를 통해서 인과성을 알아내는 것은 왜 필요한가에 대해서 이 논문이 예로 들고 있는 것 중 하나는 여러 프로세스들에 의해서 저장되는 상태의 스냅샷들에 타임스탬프를 이용해서, 전체 프로그램 상태에 대해 정상적인 상태인지 검사를 할 수 있고 이를 통해 역실행 (reverse execution), 에러의 복구, 롤백 등이 가능하다는 것입니다. 실제로 이후에 발표된 Dynamo나 Riak 등 Vector Clock을 이용하는 것으로 알려진 시스템에서는 동시적인 쓰기 등에 의해 어떤 데이터에 대해 2개 이상의 복제본이 발생했을 때 이를 해소하기 위해서 인과성을 활용하고 있는 사례를 볼 수 있습니다.

References

  • [Fidge 1998] Fidge, C.J., Timestamps in Message-Passing Systems that Preserve the Partial Ordering, Proc. 11th Australian Comp. Sci. Conf., 1988, pp. 56-66.
  • [Mattern 1998]  Mattern, F. Virtual time and global states of distributed systems. Proc. “Parallel and distributed algorithms” Conf., (Cosnard, Quinton, Raynal, Robert Eds), North-Holland, 1988, pp. 215-226.

Timestamps in Message-Passing Systems That Preserve the Partial Ordering 더 읽기"

Spotify's Engineering Culture

Spotify engineering culture (part 1) from Spotify Labs

이미 잘 알려진 서비스인 Spotify는 2008년에 창업해 2010년에 어느 정도 규모의 서비스 (1000만 사용자)에 도달, 2013년 연간 활성 사용자가 2400만명인 서비스이고, 현재 회사의 규모는 1200명 수준의 조직으로, 이제는 어느 정도 성숙해져가고 있는 엔지니어링 조직을 가지고 있는 회사라고 말할 수 있을 것 같습니다.

현재 몸을 담고 있는 회사의 문화와도 닮은 부분이 많이 있어서 공감도 되고, 두고두고 엔지니어링 문화의 지향점에 대해서 생각할 수 있는 기회가 되는 듯 해서 정리를 한번 해둡니다. 불과 10분 남짓한 비디오이므로, 엔지니어링 문화에 관심이 있다면 비디오를 반드시 한번 쯤은 시청해두면 좋을 듯 합니다.

1. Make Rules Optional

초기에는 Scrum을 사용하는 팀 문화를 가지고 있었다고 하나, 어느 순간 이러한 프랙티스들이 오히려 방해가 되었다고 합니다.

make_rules_optional

그래서, 규칙을 강제하지 않고, 프랙티스 보다는 원칙, Process Master보다는 Servant Leader를 강조하는 문화를 도입했다고 합니다.

principles_over_practices

2. Autonomous Squad

Scrum Team이었던 조직을 Squad라고 이름을 바꾸었다고 하는데요. (이름이 참 마음에 드네요!) Squad의 핵심은 자율성(autonomy)입니다. Squad는 보통 8명 이하의 작은 조직이지만, cross-functional한 조직으로 디자인, 개발, 디플로이, 유지보수, 운영에 이르기까지 end-to-end responsibility를 가지고 있다고 합니다.

autonomous_squads

Squad는 미션이나 관련된 제품에 대한 전략 등의 장기적인 미션을 가지고 있으면서도, 무엇을 어떻게 개발할 지(what to build, how to build)에 대한 단기적인 목표도 분기별로 정해진다고 합니다.

사무실은 협력을 최대한 도와줄 수 있도록 최적화되어있다고 합니다. Squad 내에서 팀원들은 서로의 모니터를 쉽게 볼 수 있도록 배치되어있으며, 계획 등을 할 수 있는 라운지가 있고, 모든 벽은 화이트보드로 되어있다고 하네요.

3. Autonomy vs. Alignment

자율성이 중요한 이유로 2가지 이유를 들고 있습니다. 하나는 동기부여(motivating)이고 다른 하나는, 결정이 내부에서 이루어지고, 의존 관계나 조율 등을 위해 다른 조직을 기다릴 필요가 없기 때문에 빠르다(fast)는 것입니다.

그렇다고 해서 회사와는 아무런 상관도 없이 흘러가는 조직이 아니라, Loosely coupled, Tightly aligned squads를 지향합니다. (Aligned autonomy!)

Autonomy와 Alignment가 서로 반대 극에 있는 개념이 아니라, 아래와 같이 다른 차원의 문제로 해석하고 있고, 오히려 Alignment로 인해 Autonomy가 가능해진다고 얘기하고 있습니다.

리더의 책임은 무엇이 해결해야할 문제이고, 왜 해결해야하는지에 대해 커뮤니케이션하는 것, Squad의 책임은 가장 좋은 해결책을 찾기 위해 서로 협력하는 것이라고 얘기하고 있습니다.

alignment_vs_autonomy

4. Cross-pollination over Standardization

pollination이란 식물의 (생식 수단으로서의) 수분을 말하는 것인데요. 어떠한 프랙티스나 도구를 전체 조직으로 표준화해버리기 보다는 하나의 조직에서 좋은 프랙티스를 도입하거나 도구를 개발하고, 이를 다른 조직에서도 채용하기 시작하고, 그것을 지원하고, 결국 de facto 표준이 되는 문화를 얘기하고 있습니다. 일관성(consistency)와 유연성(flexibility) 사이의 좋은 trade-off를 찾는다고 하네요.

cross_pollination

5. Internal Open-source Model

Spotify 내의 각각의 시스템들은 가능한한 작고 서로 decouple되도록 유지하려고 한다고 합니다. 각 시스템들은 하나 또는 몇몇 squad가 담당하고 있다고 하는데요.

만약 어떤 squad가 다른 squad가 담당하고 있는 시스템의 개선이 필요하다면 그 squad에 부탁하면 되지만, 만약 그 squad가 너무 바쁘다면 이를 기다릴 필요가 없다고 합니다. 오픈 소스 모델로 직접 수정을 하고 peer review를 받으면 되는 것 같습니다.

internal_open_source_model

6. People over *

동기부여(motivation)에 집중을 한 이후에 만족도 조사가 상승했다는 결과를 얘기하고 있습니다.

7. Community over Structure

Squard들은 위에서 얘기한대로 cross-functional 팀이지만, 역량 분야 (competency area)에 따른 Chapter라는 조직이 있는 매트릭스 조직 (matrix organization)으로, 자신의 팀장을 바꾸지 않고도 Squad를 바꿀 수가 있다고 합니다.

그리고, Squad나 Chapter와는 상관없이 서로 관심사를 공유하는 사람들은 Guild라는 가벼운 레벨의 interest group을 구성한다고 합니다.

tribe_structure

계층적인 조직 구조(structure)보다는 좀 더 커뮤너티(community)와 같은 문화를 지향하는 것을 다음과 같은 말로 요약하고 있습니다.

“If you need to know exactly who is making decisions, you are in the wrong place.”

8. Small, Frequent, Decoupled Release

릴리즈가 정말로 힘들었다라고 하는 경험을 돌아보면 많은 경우 장기간에 걸친 커다란 릴리즈였던 경우였기 때문에, 저도 작은 릴리즈를 굉장히 선호하는 편인데요. 이제는 이러한 방식이 여러 회사들에서 자리잡고 있는 것 같습니다.

small_frequant_releases

여러 squad의 결과물이 하나의 제품 화면을 구성하는 경우에도, 이를 별도로 릴리즈할 수 있도록 하고 있다고 합니다. UI 또는 시스템적으로 먼저 의존 관계를 제거화고 이를 유지할 수 있어야만 가능한 이야기라고 생각하기 때문에 굉장히 놀라운 이야기로 들리네요.

decoupled_releases

9. Self-service model

하나의 조직에서 다른 조직으로 서비스를 제공하는 방식으로 다른 조직으로 책임을 완전히 넘기는 것이 아니라, 방법을 마련해주고 실제로 실행은 그 조직에서 하는 방식입니다. 커다란 회사에서는 오히려 생존을 위해서 내부 제품을 개발하는 조직도 내부 서비스 조직으로 탈바꿈하는 경우가 있었는데, 다시 생각해볼 문제인 것 같네요. 조직이 커져가는 과정에서 어떤 형태로든 내부 서비스에 대한 concern의 분리는, 그 품질에 나쁜 영향을 준다고 생각하고 있는데, Self-service model도 그 대안 중 하나가 될 수는 있겠네요.

self_service_model

10. Release trains + Feature toggles

개발 완료되지 않은 기능들을 릴리즈에 포함하지만 이를 서비스에 나타나지 않도록 기능을 on/off할 수 있다고 합니다. 완료되지 않은 기능을 릴리즈하는 것이 조금 이상하게 생각될 수 있겠지만, 이를 통해 좀 더 일찍 통합 문제 (integration problems)를 발견할 수 있고, 적지 않은 개발 비용이 발생하는 code branch를 최소화할 수 있다고 얘기합니다.

release_train

11. Trust > Control

최근 수년간 ‘Agile at scale’이 유행하고 있었는데, 이를 위해서는 ‘Trust at scale’이 필요하다고 얘기하고 있습니다. 두려움은 단지 신뢰를 없애는 것이 아니라, 혁신도 불가능하게 만든다고 얘기하고 있습니다. (fear doesn’t just kill trust, it kills innovation.)

trust_over_control

Spotify's Engineering Culture 더 읽기"

Time, Clocks, and the Ordering of Events in a Distributed System

Leslie Lamport. 1978. Time, clocks, and the ordering of events in a distributed system.Commun. ACM 21, 7 (July 1978), 558-565.

The concept of one event happening before another in a distributed system is examined, and is shown to define a partial ordering of the events. A distributed algorithm is given for synchronizing a system of logical clocks which can be used to totally order the events. The use of the total ordering is illustrated with a method for solving synchronization problems. The algorithm is then specialized for synchronizing physical clocks, and a bound is derived on how far out of synchrony the clocks can become.

이 논문에 대해서는 Paxos Made Simple에서 이미 아래와 같은 소개를 한 적이 있습니다.

Leslie Lamport는 분산 컴퓨팅 분야에서는 너무나 유명한 분이기 때문에 따로 설명할 필요가 없을 정도입니다. 예를 들어, 1978년에 출판된 “Time, Clocks, and the Ordering of Events in a Distributed System”과 같은 페이퍼는 인용 회수로 볼 수 있는 그 영향력 뿐만 아니라 OS 수업의 읽기 과제로도 빠질 수 없는 그야말로 seminal work입니다.

1. “Happened before” 관계

가장 먼저, “Happened before” 관계라는 분산시스템 내에서 사건(event)들의 순서를 표현할 수 있는 부분순서(partial ordering)를 제안하고 있습니다.

“Happened before” relation은 분산시스템에서 구현이 어려운 물리적 시계 (physical clock)를 사용하지 않더라도 사건들의 순서를 표현할 수 있음을 보여주고 있습니다. 즉, 사건이 발생한 전역적으로 통용되는 시각을 알지 못해도 우리는 자연스럽게 사건의 순서를 정할 수 있습니다.

또한, 서로 다른 프로세스 사이에서 메시지를 주고 받을 경우에 사건 사이의 인과성(causality)이 발생하는 것을 다음과 같은 정의에 담고 있습니다.

Definition. The relation → on the set of events of a system is the smallest relation satisfying the following
three conditions:

  1. If a and b are events in the same process, and a comes before b, then a → b.
  2. If a is the sending of a message by one process and b is the receipt of the same message by another process, then a → b.
  3. If a → b and b → c then a → c.

Two distinct events a and b are concurrent if a ↛ b and b ↛ a. Assume a ↛ a for any event a. So → is an irreflexive partial ordering on the set of all events in the system.

2. Logical Clocks

논리적 시계는 하나의 프로세스 내의 각 사건들에 대해 단조 증가하는 숫자를 할당하는 것으로 볼 수 있으며, 물리적 시계가 아니라 사건이 발생한 순서에 기초해야 합니다.

Clock Condition. For any events a, b:
if a → b then C(a) < C(b).

“Happened before” 관계의 정의에 따라, 각 프로세스는 사건이 발생할 때마다 증가하는 타임스탬프를 부여하며, 프로세스 사이에 메시지를 송신할 때 타임스탬프를 함께 송신하며, 메시지를 수신하는 측에서는 수신한 타임스탬프보다 더 큰 타임스탬프를 새로운 사건에 할당합니다.

3. Ordering the Events Totally

위에서 정의된 논리적 시계만으로는 분산시스템 내의 사건들의 완전순서(total ordering)는 불가능하기 때문에, 프로세스 사이의 임의의 순서(!)를 도입해, 완전순서를 만들 수 있습니다.

In case two or more events occur at the same time, an arbitrary total ordering ≺ of processes is used. To do this, the relation ⇒ is defined as follows:

If a is an event in process Pi and b is an event in process Pj , then a ⇒ b if and only if either:
i. Ci<a> < Cj<b> or
ii. Ci<a> = Cj<b> and Pi ≺ Pj

이렇게 정의된 완전순서를 이용해 분산시스템에서의 상호배제(mutual exclusion) 문제를 해결하는 방법을 제시하고 있습니다.

간단히 얘기하면, 어떤 프로세스가 자원을 요청할 때는 자신의 타임스탬프를 함께 다른 모든(!) 프로세스들에게 전송하고, 이 자원의 요청은 요청한 프로세스 뿐만 아니라 모든 프로세스의 큐에 위에서 정의된 완전순서대로 정렬됩니다. 이 큐에서 가장 앞에 있는 자원 요청이 자원을 획득해야한다고 볼 수 있는데, 모든 프로세스들이 동일한 큐를 유지해야하기 때문에, 자원 획득을 위해서는 모든 다른 프로세스들로부터 receipt 메시지를 수신한 조건에서만 자원 획득이 가능합니다. 또한, 다른 프로세스의 자원 요청에 대한 응답과 자신의 자원 요청의 (타임스탬프의 순서는 올바르다고 하더라도) 전송 순서가 바뀌는 경우는 두 프로세스 사이의 통신은 순서대로 일어난다는 가정에 의해 발생하지 않습니다.

이 구현은 1개 이상의 프로세스의 실패나 메시지의 소실 등을 가정하고 있지 않기 때문에 현실적으로 사용할 수 있는 알고리즘은 아니지만, 분산시스템에서의 완전순서의 유용성을 보여주고 있다고 생각합니다. 그리고, Lamport가 이후에 제안한 Paxos가 바로 현실적인 환경 하에서의 완전순서를 보장하기 위한 방법을 제공하고 있는 것으로 보입니다.

4. Anomalous Behavior

위에서 제시한 상호배제 알고리즘에서 사건 사이의 인과성이 외부화됨으로써 발생할 수 있는 문제를 제시하고 있습니다. 예를 들어, 자원 요청 A를 한 후, 전화를 걸어 다른 컴퓨터에서 자원 요청 B를 한 경우, 자원 요청 A와 자원 요청 B 사이에는 실제로 인과성이 존재하지만, 논리적 시계의 체계는 이를 인지하지 못하므로, 자원 요청 B가 더 낮은 타임스탬프를 획득해 먼저 자원을 획득할 수 있다는 것입니다.

이를 해결하기 위한 방법으로 2가지 방법을 제시하고 있는데, 첫번째는 “happened-before” 관계에 필요하지만 외부화된 정보를 시스템 내로 도입하는 것입니다. 즉, 자원 요청 B를 하는 사용자에게 자원 요청 A 보다 더 이후의 타임스탬프를 발급하도록 자원요청 A의 타임스탬프를 전화를 통해 알려주는 방법 등으로 논리적 시계 체계를 유지하는 책임을 부여하는 것입니다.

다른 방법은 외부화된 사건들 사이의 관계를 포함해 모든 사건들을 정렬할 수 있는 물리적인 시계의 체계를 구성하는 것입니다. 이 시계들은 다음의 Strong Clock Condition을 만족해야 합니다.

Let S be the set of all system events and S be the set containing S along with relevant events external
to the system. Let ↪ denote the “happened before” relation for S.

For any events a, b in S: if a ↪ b then C<a> < C<b>.

5. Physical Clocks

Strong Clock Condition을 만족하기 위해서는 물리적 시계는 다음과 같은 조건을 만족해야합니다.

Let Ci(t) denote the reading of clock Ci at physical time t. Assume that Ci(t) is a continuous, differentiable
function of t except for isolated discontinuities introduced by clock resets.
PC1. There exists a constant k << 1 such that for all i: |dCi(t) / dt – 1| < k.
PC2. For all i, j : |Ci(t) – Cj(t)| < e.

PC1은 물리적 시계가 가는 속도가 물리적 시간이 흐르는 속도와 일정 오차 범위 내에 있다는 것을 의미합니다. 일반적인 수정 발진 방식의 시계의 경우, k는 약 10-6정도로 언급하고 있으며, PC1 자체는 만족되는 것으로 가정하고 있습니다.

한편, PC2는 물리적 시계들 사이의 오차가 일정 범위 내에 있다는 것을 의미합니다. PC2를 보장하기 위해서 물리적 시계의 보정을 위한 구현 방법을 제시하고 있습니다.

Let vm = t’ – t be the total delay of m which is unknown to the receiving process. Let µm be some minimum delay >= 0 known by the receiving process such that µm <= vm.

IR2′. a. If Pi sends a message m at physical time t, then m contains a timestamp Tm = Ci(t).
b. Upon receiving a message m at time t’, process Pj sets Cj(t’) equal to max(Cj(t’ – 0), Tm +
µm).

메시지에 타임스탬프를 넣어서 보내고, 이를 수신하는 측에서는 메시지를 통해 받은 타임스탬프와 최소 통신 지연 시간 이후의 시각으로 시계를 재설정하는 방식이라고 할 수 있고, 이러한 구현 요구사항을 만족한다면, PC2를 만족하는 것을 증명할 수 있다고 합니다. 이 증명에서는 일정 시간 내에 메시지가 전체 프로세스 사이로 전송되는 상황을 가정하고 있으므로, 메시지를 주고 받지 않는 조건을 염두에 두고 있는 것 같지는 않습니다.

한편, 최소 지연시간에 해당하는 µm은 일반적으로 거리와 빛의 속도로 계산할 수 있는 수준의 값으로 언급되고 있습니다. 그리고, 주어진 µm에 대해 k와 e가 얼마나 작아야 하는지에 대한 계산 방법도 설명하고 있습니다.

현실적으로는 이 논문에서 정의된 Physical Clock은 항상 가장 빠른 시계에 맞춰지게 되므로 실제 시간 (physical time)보다 더 빨라지게 되겠지만, 분산시스템의 동기화 문제를 해결하는 능력과는 무관하다고 할 수 있을 것 같습니다.

6. Closing

이 논문은 분산시스템의 문제에 대한 이해에 가장 중요한 사고 도구로 사용할 수 있는 중요한 개념들을 정의하고 있는 것 같습니다. 내용 자체를 정확하게 이해했는지의 여부를 차치하더라도, 이러한 개념이 마음에 와닿기 위해서는 몇 번은 더 읽어봐야 할 것 같습니다.

다음에는 Vector Clock에 관한 논문인 C. Fidge의 Timestamps in Message-Passing Systems That Preserve the Partial Ordering을 읽어볼 예정입니다.

Time, Clocks, and the Ordering of Events in a Distributed System 더 읽기"

Actors in Scala

 

Actors in ScalaActors in Scala by Philipp Haller and Frank Sommers

150페이지 남짓의 이 책은 Scala의 Actors 라이브러리에 대한 책이다. 이 책의 저자 중 한명인 Philipp Haller는 Scala Actors 라이브러리의 저자다.

이 책은 Scala Actors를 다루는 것에 대한 기본적인 내용과 Exception/Termination handling, Actor 실행 방법의 customization, Remote Actors를 상세하게 다루고 있다. 원래는 Actor를 사용하는 패턴도 기대하고 있었지만 MapReduce와 같은 몇가지 예시 정도 외에 좀 더 완전한 내용의 것은 찾을 수 없었다. 하지만, 기본적인 Actors 라이브러리의 기본적인 개념을 익히는데에는 좋은 책일 듯 하다.

한가지 문제라면, Scala 2.10 부터는 Actors 라이브러리가 deprecated 되었고, Akka로 대체되었다는 것이다. Scala Actors의 자세한 히스토리는 잘 모르지만, Akka는 Scala Actors와 커다란 차이는 없는 반면 더욱 일관성이 있는 느낌이 든다. Scala Actors와 Akka의 차이에 대한 사항은 Scala Actors Migration Guide를 참고하면 좋을 듯 하다.

Akka는 Java와 Scala 모두 지원하고 있기 때문에, 기존에 Java 위주의 프로젝트를 진행하고 있었지만 Scala 프로젝트도 함께 진행하기 위해 연동해야 하거나 Scala 프로젝트로 전환하는 경우의 통합 수단으로서, 기존의 language-agonostic RPC들, ZeroMQ 등의 대안으로 좋은 선택이 될 수 있지 않을까 생각해보고 있다.

Actors in Scala 더 읽기"

소중한 것을 먼저 하라. (First things first)

최근 한달 동안 frustrating things를 지난 주에 적어 본 것이다.

1. 누군가가 찾아오거나 메신저로 물어보거나 메일을 보내온 일들을 처리해주다 보면, 일과 시간 내내 새로이 발견된 문제를 해결하는 문제를 처리하고 있거나, 아마도 다른 사람에게 갔어야 하거나 지금까지 몇번이나 반복되었던 듯 한 누군가의 질문에 답해주거나, 업무의 경과를 공유 또는 보고하는 문서나 메일을 쓰고 있다. 상사로부터 명시적으로 부여받은 소위 ‘본업’에 해당하는 일이나 중요하다고 생각하는 일은 어느새 아무도 방해하지 않는 밤이 되어서야 하게 된다. 또는 밤에도 그러지 못하는 경우도 있다.

2. 정작 ‘본업’을 할 시간이 생겨도 실제로 어떤 가치를 만들어내는 일 보다는, 그 일을 위한 일 – 이슈를 공유하거나 할 일을 정하기 위한 회의, 도구의 문제를 해결하는 일, 빌드 환경의 문제, pull request를 어떻게 할 지 정하는 문제 등을 해결하는 일 등에 들어가는 시간이 많다.

이렇게 문제를 정의한 후에는, 매일 아침 출근할 때마다 ‘오늘은 본업에만 집중할거야. 그리고 조금 여유가 생기면 내가 쓰고 싶었던 코드를 쓸거야.’라고 되새기지만, 그 전날과 완전히 동일한 하루를 보낸다. 이러한 일상의 문제들을 잘 처리하면서 자신의 ‘본업’도 잘하는 사람들도 주변에 있다고 생각하기 때문에 실은 이러한 반복적인 문제의 원인이 내 자신의 습관에 있는 것이 아닐까 이런 생각을 하면서 집으로 돌아온다. (내향적인 성격의 전형적인 결론)

이처럼 정확한 원인을 모르는 것에 대해 스트레스를 받는 것을 해결하는 방법 중 하나는 이렇게 생각을 정리해보거나, 느끼고 있는 것에 대해 다른 사람과 얘기를 하거나, 그냥 좋아하는 일을 하면서 쉬는 것이다. (그래서, 집에서 이 글을 쓰고 있다.)

그렇다. 누군가는 중요해질지도 모르는 급한 문제들을 살펴봐야 하고, 누군가는 누군가의 질문에 답해주어야 하고, 누군가는 문서를 잘 정리해야 하고, 이슈는 빠르게 공유되어야 하고, 원래 실무를 하는 과정에서는 여러가지 문제들이 발생하게 마련이다.

그런데, 좀 더 넓게 바라보면, 내가 하고 싶은 것은 다음과 같다.

– 많은 사람들에게 가치를 주는 중요한 일을 하고 싶다.
– 나의 취향과 호기심, 재미를 충족시켜주는 사람들과 일하고 대화 하고 싶다.
– 최대한의 역량을 발휘하면서 일하면서 성장하고 또 그 결과로 인정받고 싶다.
– 나의 행동을 통해 가족들이 행복할 수 있도록 해주고 싶다.
(누구나 바랄법한 목록 아닌가 싶지만, 사람들마다 미묘하게 다르다.)

잠깐씩은 ‘그래, 어쩔 수 없지~’ 하다가도 이 목록을 보다보면 진정 내가 원하는 것을 얻기 위해서는 뭔가 변화가 필요하다는 것을 알 수 있다. 그런데, 그 변화를 위한 길은 걱정이 되는 강한 용기와 의지가 필요한 매우 어려운 일인 것 같다.

예를 들어, 반복하는 단순한 운영 업무 대신 ‘이것을 반복하지 않도록 하는 일을 해보죠’라고 한다면 모든 사람의 환호성을 듣기는 어려울 것이다. 누군가가 열심히 만든 도구를 버리고 내가 쓰기 편한 도구를 쓰자고 한다면 수많은 그렇게 할 수 없는 이유들이 나열될 것이다.일부로 메신저 친구 등록을 하면서 질문을 해왔는데 만약 메일로 다시 보내달라고 한다면 저 사람 답답하게 일하네란 소리를 들을 것이다. 또는 그럴까봐 걱정을 해야할 것이다.

똑같은 문제로 힘들어 하고 분들은 어딘가에 많이 있을거라고 생각하지만, 참 쉬운 문제가 아니다. 일단 쓸데없는 오지랍이라도 줄여보려고 노력해야할 것 같다.

스티븐 코비 나쁜 놈.

소중한 것을 먼저 하라. (First things first) 더 읽기"

Hacking Culture

Hacking Culture by Jesse Robins

QCon San Francisco 2012에서 Chef로 유명한 Opscode의 공동창업자인 Jesse Robins가 발표한 내용입니다. Chef나 Opscode에 대한 홍보가 섞여있고, 내용은 어디선가 들어봤을 법한 내용들이었지만, 자신의 이야기를 곁들여서 재미있고 한층 더 마음에 와닿게 설명을 하고 있는 것 같습니다.

Velocity 2009

요즈음 유행하고 있는 DevOps라는 개념이 처음 나온 것은 Velocity 2009에서의 John Allspaw가 발표한 “10 Deploys per Day: Dev and Ops Cooperation at Flicker” (Slides)라는 강연입니다. Jesse Robins의 강연도 이 강연의 일부 내용을 다시 소개하고 있는 것 같군요.

Continuous Delivery

장기간에 걸친 커다란 변경은 위험하기 때문에 작은 양의 코드를 좀 더 자주 배포해야한다는 개념을 Change monster라는 그림을 통해 설명하고 있습니다.

hacking_culture_00

결국 더 빠르게 비즈니스 가치로 이어지고, 버그를 방지할 수 없는 한 버그를 더 빨리 고칠 수 있으며, 개발자들은 자신이 변경한 것을 바로 볼 수 있기 때문에 즐겁게 일할 수 있다는 내용입니다.

DevOps

‘테스트는 통과했으니 이제 운영자의 책임이야’, ‘제가 필요로 하는 권한이 없어’ 같은 전통적인 개발-운영의 문제를 풀기 위해서는 단지 도구가 아니라 서로 신뢰하는 환경이 필요하다고 얘기하고 있습니다.

조직 구조가 제품의 구조를 결정한다는 얘기를 Conway’s law를 빌려 이야기 하고 있습니다.

하나하나 설명하기는 힘들지만, 아래의 그림 한장이 DevOps의 전체 스택을 보여주는 것 같군요.

 

 

hacking_culture_01

Changing Culture

Toyota Production System (이하 TPS)이 한창 유행할 때 모두가 이를 벤치마킹해서 똑같은 시스템을 만들었지만, 가장 핵심적인 요소라고 할 수 있는 누구든지 문제의 해결을 위해서 라인을 정지시킬 수 있는 것은 따라하지 못했다고 얘기하면서 문화의 중요성을 강조합니다.

문화를 바꾸기 위한 다섯가지 조언을 하고 있습니다.

1. Start small, build trust & safety

작은 것은 위협도 되지 않거니와 무시해도 좋다고 생각하기 때문에 거부감을 가지지 않습니다. 사람들에게는 그저 실험이라고 얘기하라고 하고 있습니다.

2. Create champions

자신이 일으키는 변화를 신뢰하고 지원하는 관리자가 있어야 합니다. 그리고, 주변 사람들 모두에게 credit을 주고, 변화와 관련된 사람들에게 특별한 상태 (예를 들어 ‘이달의 직원’)를 주어 그들이 새로운 변화에 대해 더욱 많은 이야기들을 하도록 해야합니다.

3. Use metrics to build confidence

변화를 지지할 수 있는 KPI (예를 들어, MTTR)를 찾아서 그것을 통해 사람들에게 가치를 보여주고, 나중에는 변화하지 않을 경우의 비용을 보여주는 용도로 사용합니다. 사람들에게 변화와 관련한 이야기를 들려줄 때 데이터를 가지고 이야기합니다.

4. Celebrate successes

사람들과 문제를 극복한 사례에 대해 긍정적인 면을 이야기 합니다. 절대로 문제를 만들어낸 사람들에 대해서는 이야기 하지 않습니다.

5. Exploit compelling events

언젠가는 변화를 위한 중요한 기회가 자연스럽게 찾아오게 됩니다. 중요한 것은 이 때 ‘I told you so’가 아니라 ‘What do we do now’라고 이야기할 수 있어야 합니다.

Hacking Permission

어떤 사람들은 스스로의 시간을 털어서 다른 사람들에게 도움이 되는 옳은 일을 하려고 하지만 보통 권한이 없기 때문에 그렇게 하지 못합니다. 그들에게 “site directors”와 같은 권한을 주라고 얘기합니다.

hacking_culture_02

Don’t Fight Stupid, Make More Awesome

이 강연에서도 언급했다시피 변화를 일으키는 것에는 많은 시간과 인내심이 필요한데, 이 문구를 되새기면 언제든지 다시 힘을 낼 수 있을 것 같은 느낌이군요.

hacking_culture_03

Hacking Culture 더 읽기"

Programming in Scala

Programming in Scala 2nd EditionProgramming in Scala, Second Edition

2013년이 시작하고 얼마 지나지 않아 트위터에서 개발자 저마다 개인적으로 2012년의 프로그래밍 언어를 꼽는 것이 유행한 적이 있다. 조금 늦었지만, 내게 2012년 한 해의 언어를 꼽으라면 Scala가 될 것 같다.

가장 큰 이유는 두가지로, 첫번째는, (정확히 세어보지는 않아서 모르겠지만 아마도) 2012년 동안 가장 많은 라인을 코딩한 프로그래밍 언어가 Scala라는 것, 두번째는, Programming in Scala를 읽었다는 점이다.

“The Scala Programming Language”

이 책의 주 저자라고 할 수 있는 Martin Odersky는 바로 Scala 언어의 설계자로, 즉 이 책은 흔히 “The XXX Programming Language”에 해당하는 책이라고 할 수 있다. 책의 내용은 Scala의 전반적인 특징들을 예제를 통해서 익히는 튜터리얼 성격의 도입부와 주요한 문법들을 설명하는 부분, 클래스 라이브러리에 관한 부분으로 나누어져 있다고 볼 수 있는데, 지루해 보이는 예제 프로그램을 여러 장에 걸쳐서 계속해서 써먹고 있다는 것을 빼고는 잘 쓰여진 프로그래밍 언어 서적이라고 생각한다. 따라서, Scala 언어를 공부하고자 한다면 이 책을 읽는 것을 추천해도 무리가 없으리라 생각한다.

Scalable Language

이 책을 읽으면서 Scala 언어를 좋아하게 된 가장 큰 이유 중 하나는, 매우 일반적인 문법 토대를 세우고, 다른 문법 요소나 클래스 라이브러리, Java 언어와의 호환성을 그 위에 일구어 냈다는 것이다. 예를 들어, 패턴 매칭(match…case 구문)이 예외 처리나 Actor에서도 사용되는 것이라든지, 기본형이나 컬렉션 클래스들의 Java 호환성을 implicit conversion을 이용해서 해결하는 것과 같은 것들이다. Java 언어를 공부할 때, 특정한 클래스들이 문법의 요소로 사용되는 것이 마음에 들지 않았는데, Scala는 그런 면에서는 오히려 C++ 언어 template을 이용한 확장성 있는 문법을 보는 듯한 느낌이다. 물론 이 언어의 이름인 Scala도 Scalable Language를 의미하는 것이다.

The Throne Threatened

한편, 최근 몇 년간 나의 과제 중 하나는 JVM 환경에서 적절한 glue language를 찾는 것이었다. 그 과정에서 물망에 올랐던 JRuby는 Java와의 호환성 면에서 프로그래머를 괴롭게 만드는 여러가지 문제들이 발견되어 포기했고 (지금은 해결되었을런지도 모르겠다), Groovy는 초기의 기대에 비해 너무나 인기를 끌지 못해서 다른 사람들을 설득하기가 어려웠는데, 반면, Scala 언어는 Java의 기본형이나 시스템 클래스들, 클래스 라이브러리들과의 호환성이 위에서 언급한 것과 마찬가지로 매우 세심하고 우아한 형태로 준비되어 있는 동시에, 어느 정도는 사람들의 이목을 끌었다는 장점이 있다. 오히려 Java의 개선 방향을 제시해주는 것은 아닐까 생각이 들 정도로 JVM 환경의 언어 수준을 한층 더 끌어올린 것 같다.

Closing

이 책을 읽은 것은 몇 달 전의 일이지만, 이제 Pattern matching과 Actor를 쓰기 시작하는 정도에 익숙해진 정도로 대체로 아직은 Java 코드 수준과 크게 다르지 않은 수준의 코드를 쓰고 있기 때문에, Scala 언어로 쓰인 오픈소스 프로젝트의 코드를 통해 좀 더 Scala다운 스타일의 좋은 코드들을 경험해보는 것이 좋을 것 같다.

Further Reads

 

 

 

Programming in Scala 더 읽기"

The Facebook Release Process

The Facebook Release Process by Chuck Rossi

사용자들이 항상 사용하고 있는 서비스를 하면서 빠르게 변화하는 것은 두마리 토끼를 잡으려는 것과 같이 어려운 일이기 때문에 많은 고민과 노력을 통한 좋은 프랙티스가 필요하다고 생각되지만, 실제로는 그러한 프랙티스는 그다지 널리 알려져 있지는 않는 것 같다.

이 발표는 QCon SF 2012의 발표 중 하나로, Facebook의 Release Engineering을 2008년부터 지금까지 담당해온 Chuck Rossi가 Facebook의 Release Process를 소개하고 있다.

Facebook의 개발자나 코드의 규모는 상당히 큰 편이지만, 릴리즈의 속도는 현재 일하고 있는 서비스의 그것과 거의 유사해서 이 발표를 통해 어떤 면에서는 자신감을 얻을 수 있었고, 반면에 앞으로 개선할 수 있는 많은 영감들을 얻을 수 있었던 것 같다.

이 발표의 주요한 점들을 요약하면 아래와 같다.

Weekly Release & Daily Releases

우선 trunk, lastest, production 3개의 branch로 관리되고 있다. 매주 일요일 오후 6시에 trunk로부터 lastest가 생성되고, 이를 이틀 동안 테스트한 뒤에 production으로 push가 되어 release가 된다. 또한, 매일 300개 가량의 cherrypick을 통해 production으로 릴리즈되고 있다고 한다. 작은 크기의 release를 더욱 자주할 것을 권장하고 있다.

Dogfooding

Facebook의 모든 직원들은 facebook을 사용할 때, www.lastest.facebook.com으로 redirection된다고 한다. 더욱 테스트를 잘하기 위한 이유도 있겠지만, 서비스에 문제를 일으켰을 때, 사용자들이 느낄 고통을 직원들이 느껴보라는 이유도 있다고 한다. 그리고, 이 내부 서비스에 문제가 생기더라도 릴리즈 매니저가 롤백을 하지 않고 고칠 때까지 그대로 둔다고 한다.

Self Service

개발자 개개인이 릴리즈하고자 하는 commit을 추적하기 위해서 릴리즈 매니저에게 메일을 쓴다든가 물어보는 것이 아니고, IRC bot을 통해 자신의 commit이 현재 어떤 상태인지 추적할 수 있다고 한다.

 

Test Automation

Weekly Release는 이틀간의 테스트 기간이 있지만, Daily Release는 그렇지 않은 것 같은데, Daily Release의 테스트는 어떻게 이루어지는가의 의문이 남는데, 자세히 언급하고 있지는 않지만, 일단 자동화된 테스트들이 굉장히 많으며, 이들에 의존하는 것이 아닌가 싶다.

Error Tracking / Perflab

에러의 종류별로 발생 빈도나 API의 응답 속도 등의 트렌드를 그래프로 살펴볼 수 있고, 이를 릴리즈 시기와 비교할 수 있기 때문에, 어떤 릴리즈가 regression을 발생시켰는지를 쉽게 파악할 수 있다. 에러에 직접적으로 관련된 소스 코드를 통해 문제를 일으킨 개발자를 쉽게 찾을 수 있다.

Gatekeeper

어떤 기능을 정해진 조건의 사용자들에게만 릴리즈할 수 있다. 실험적인 기능을 소수의 사용자에게 먼저 릴리즈하고 안정화를 거친 후 전체 사용자에게 릴리즈할 수 있는 bucket test 등의 용도로 사용할 수 있다. Facebook의 다양한 개인 정보들을 가지고 분류할 수 있다.

Push Karma

어떤 commit의 규모 (추가, 변경, 삭제된 라인의 수), 논란이 되는 정도 (review 상의 comment, rejection) 등을 막대 그래프로 시각화 하고 있고, 릴리즈 매니저만 볼 수 있는 개발자에 대한 Like/Dislike 버튼이 있어서 어떤 commit의 위험성을 가늠할 수 있도록 도구를 구성하고 있다.

BitTorrent

수천대에 이르는 서버에 빠른 시간 내에 배포하기 위해서 BitTorrent를 이용하고 있다. 예전에 일했던 팀에서는 비슷한 이유로 Binary Tree 형태로 rsync 구동 플랜을 짜서 배포했던 적이 있었다.

Culture

릴리즈 관리자가 사용할 수 있는 도구는 소프트웨어적인 도구와 문화라고 얘기할만큼 개발 문화의 중요성을 강조하고 있다. 항상 그렇지만, 도구만으로는 성공할 수 없다.

Further Reads

 

 

 

 

The Facebook Release Process 더 읽기"

What consistency does your key-value store actually provide?

What consistency does your key-value store actually provide? by Anderson, Eric, et al

Many key-value stores have recently been proposed as platforms for always-on, globally-distributed, Internet scale applications. To meet their needs, these stores often sacrifice consistency for availability. Yet, few tools exist that can verify the consistency actually provided by a key-value store, and quantify the violations if any. How can a user check if a storage system meets its promise of consistency? If a system only promises eventual consistency, how bad is it really? In this paper, we present efficient algorithms that help answer these questions. By analyzing the trace of interactions between the client machines and a key-value store, the algorithms can report whether the trace is safe, regular, or atomic, and if not, how many violations there are in the trace. We run these algorithms on traces of our eventually consistent key value store called Pahoehoe and find few or no violations, thus showing that it often behaves like a strongly consistent system during our tests.

예전에 HP-KVS에 관련해서 자료를 찾다가 발견한 페이퍼인데, 얼마전 한국에 다녀올 때 읽어보게 되었습니다.

1. Perceived consistency rather than worst-case consistency

이 페이퍼는 일반적으로 key-value store들이 보장하는 worst-case consistency가 아니라, 실제로 client에 의해서 관찰되는 consistency의 수준을 측정하는 알고리즘을 제안하고 있다. 우리가 스토리지 기술을 선택할 때는 물론 worst-case consistency가 고려되기는 하지만, 실제로는 ‘실용적인’ 접근을 취하는데, 그것이 의미하는 바는 애플리케이션의 액세스 패턴에 따라 사용자가 느끼는 consistency의 수준이 달라질 수 있음을 고려해서 스토리지 기술을 선택한다는 것이다. 이 페이퍼가 해결하려는 문제 자체가 엄밀하거나 학술적이기 보다는 실용적인 의미를 해석하려는 것이기 때문에 한계는 있겠지만, 어떤 worst-case consistency를 가진 스토리지 – 예를 들어 eventually consistent 스토리지들이 어떤 애플리케이션에 필요한 consistency를 달성하기에 충분한지 충분하지 않은지에 대해서 매우 피상적으로 논의하는 것보다는 체계적인 방법을 제공한다는 점 그리고, 그러한 방법이 존재할 수 있다는 점에서 의미가 있는 것 같다.

2. A eager, eventually consistent protocol often achieves strong consistency

이 알고리즘을 통한 검증을 역시 HP에서 만든 eventually consistent key-value store인 Pahoehoe를 가지고 실험한 결과를 보여주고 있는데, 가장 concurrent한 조건 (128 concurrent processes on 1 key)에서도 consistency violation의 수가 10% 이하로 발생하고 있고, 일반적인 조건 하에서는 1% 수준이다. 그 이유를 우리가 일반적인 웹 애플리케이션에서 예상하고 있는 것과 마찬가지로 concurrent write 하에서의 read가 많지 않기 때문으로 설명하고 있다.

3. Lamport’s consistency assumption on registers: safe, regular, and atomic

이 페이퍼가 검증하려고 하는 consistency 수준의 분류로 Leslie Lamport가 On Interprocess Communication. Part I: Basic Formalism에서 제안한 register의 3가지 consistency semantic을 사용하고 있다. 이는 다음과 같다.

3가지의 consistency 모두 write와 concurrent하지 않은 read는 가장 최근의 write에 의한 값을 return 해야한다. 차이는 write와 concurrent한 read에서 발생한다.

  • safe: write와 concurrent한 read는 임의의 값을 return
  • regular: write와 concurrent한 read는 가장 최근의 write에 의한 값과 concurrent한 write들에 의한 값들 중 하나를 return
  • atomic: write와 concurrent한 read도 가장 최근의 write에 의한 값을 return

worst-case consistency를 가지고 예를 든다면, 최근 유행하는 eventual consistent storage들은 concurrent하지 않은 read에 대해서 가장 최근의 write에 의한 값을 return하는 것을 보장하지 않으므로 가장 느슨한 수준인 safe 조차 만족하지 못한다. 반면에 일반적인 ACID 데이터베이스는 atomic 수준에 해당한다.

4. Methods

이 페이퍼가 제안하고 있는 알고리즘은 대략 다음과 같다.

  1. 어떤 key-value store에 대한 클라이언트의 모든 액세스에 대해 시작 시각과 종료 시각, 그리고 저장하거나 읽어온 값의 로그를 기록한다.
  2. 이 로그를 바탕으로 오퍼레이션이 vertex이고, should-happen-before 관계가 edge인 directed graph를 구성한다. 이 때 이 관계는 검증하려는 consistency 종류에 따라서 달라지는데, 대체로 시간의 관계, 값의 인과 관계를 의미한다고 보면 된다.
  3. 구성된 graph에서 cycle이 발견되지 않으면 consistent, 발견되면 inconsistent하다고 판단한다.

straight-forward하기 때문에 쉽게 이해할 수 있다. 시각의 정확성이나 값의 인과관계를 찾는 부분 등에서 보완이 필요한 것 같긴 하지만 중요한 문제는 아닌 것 같다.

5. Measuring Consistability

여러 eventually consistent 스토리지들은 failure가 발생했을 때 consistency를 희생하게 되어있는데 이 때의 consistency 희생이 어느 정도인지 측정하는 작업이 필요하다.

6. Further Reads

  • J. Misra, Axioms for memory access in asynchronous hardware systems, 1986.
  • L. Lamport, On interprocessing communication, Part I: Basic formalism and Part II: Algorithms, 1986
  • W. Vogels, Eventually consistent, 2009
  • A. Aiyer, et al., On the availability of non -strict quorum systems, 2005
  • E. Anderson, et al., Efficient eventual consistency in Pahoehoe, an erasure-coded key-blob archive, 2010

What consistency does your key-value store actually provide? 더 읽기"