요구 사항 : "채널 서버와 게임 서버 모두에서 아이템을 사용 할 수 있게 해주세요"
개발자 관점에서 해석 -> 서로 다른 분산 컴포넌트에서 같은 기능들을 사용 할 수 있게 해주세요
용어 정의 : 컴포넌트. 분산 시스템 구성 요소.

문제 상황 : "채널 서버와 게임 서버는 서로 다른 컴포넌트다"
채널 서버와 게임 서버가 가지고 있는 데이터와 데이터를 유지하는 자료 구조가 다르기 때문에 추상적으로는 '아이템 사용'이라는 같은 기능이지만 구현 방법은 서로 다르다.

예를 들어 채널 서버는 데이터 A, B, C를 항상 유지하고 있고, 게임서버는 B 데이터만을 가지고 있다고 가정하자. 아이템 사용을 위해서는 A, B, C 데이터가 필요하다고 할 때, 채널 서버는 필요한 데이터들을 이미 가지고 있으므로 아이템 사용에 별다른 준비 과정이 필요 없지만 게임 서버는 A 만 가지고 있으므로 B, C를 얻어 오는 부분이 따로 구현 되어야 한다. 또한 채널 서버는 아이템 사용 결과만을 클라이언트에게 리턴하면 되지만 게임서버는 아이템 효과들을 캐릭터 정보에 반영 해야하는 이슈 처럼 아이템 사용 결과를 처리하는 방식도 두 컴포넌트간에 서로 다르다.

따라서 기능이 변경 되는 경우 그에 맞춰 항상 두 곳을 수정 해야 하는 이슈가 발생한다.

생각의 시작..기능 변경시 두 곳을 고치지 않고 공통 기능을 사용하는 방법이 없을까?

1. 코드 레벨에서의 공유
동일한 코드를 파일 링크 등을 통해 두 컴포넌트에서 공유

장점 :

- 동일한 코드를 재사용 할 수 있는 경우라면 직관적이며 구현이 간단 하다는 장점이 있다
- 위와 같이 동일 코드를 적용 할 수 없는 경우라면  코드 레벨에서 공유는 장점이 없다.
단점 :
- 결국 호출 부분 외에 다른 부분들은 서로 다른 code snippet을 가지게 되며 이는 파일 링크 등을 통한 코드 레벨에서 공유는 기능 변경 이슈 발생 시 항상 두 부분을 동시에 수정해야 하는 유지 보수 비용을 크게 감소 시키진 못한다.
- #ifdef 등 컴파일 플래그를 이용한 공유는 코드 분석 및 유지 보수 비용 증가
- 개발자는 항상 하나의 기능이 두 컴포넌트에 구현 되어 있음을 알아야 하는 유지 보수 비용 증가

2. 모듈(dll, lib or so) 레벨에서 공유
공통 기능을 모듈화 시키고 각 컴포넌트에서 모듈을 import 하는 방식으로 공유

장점 :

- 추상화(eg. "아이템을 사용한다. 하지만 난 자세한 사항은 모르겠다")가 잘 정의되었다는 가정하에 중복 코드 개발 비용을 줄일 수 있다.
단점 :
- 추상화를 위해 모듈내에서 사용하는 데이터가 이미 컴포넌트에 존재하고 있는 데이터와 중복이 발생하는 경우 저장 공간 낭비, 성능 낭비등의 문제와 동일 데이터에 대한 동기화 문제가 발생 할 수 있다.
- 성능이나 기존 컴포넌트 데이터들과의 호환성을 위해 각 컴포넌트마다 다른 추상화 모듈을 제공한다면 코드레벨 공유와 같은 단점을 가지게 된다.
- 컨넥션이 변경 될때마다 데이터 로딩과 같은 초기화 작업들을 다시 해줘야 한다. 컨넥션이 자주 바뀌고 기능의 사용이 빈번하다면 성능 이슈가 발생 할수 있다.
- 모듈에서의 장애가 서버 컴포넌트까지 확장 된다. 만일 장애 파급 효과를 제한하기 위해 중요한 기능들만 따로 모아 컴포넌트를 분리한 경우라면 분리의 의미가 없어진다

3. 컴포넌트 레벨에서 공유(back-end 방식)
공통 기능을 처리하는 back end 서버를 두고 front-end 서버들이 질의 하는 방식

장점 :
- '모듈 레벨에서 공유'의 장점에 추가하여 컨넥션이 변경 되더라도 기존 데이터들을 유지 할 수도 있다.
- 장애 파급 효과를 제한 할수 있으며 하나의 컴포넌트에서 장애가 나도 다른 컴포넌트에 질의 하는 형식으로 장애를 극복 할 수 있다.
단점 :
- 추가적인 메시지 트래픽 비용
- front-end <-> back-end 컴포넌트간 메시지를 릴레이 하는 기능 추가 구현 비용. 메시지 내용이 변경 되는 경우 릴레이 부분도 항상 같이 수정해 줘야 하므로 새로운 유지 보수 포인트가 발생 할 수 있다.
- 메시지 시퀀스가 길어짐으로써 시스템 복잡도 증가

4. 컴포넌트 레벨에서 공유(front-end 방식)
클라이언트와 직접 연결을 맺는 공통 기능 컴포넌트를 두고 클라이언트가 계속 연결을 유지하며 공통 기능이 필요할 때마다 질의하는 방식

장점 :
 - back-end 컴포넌트 레벨 공유 방식의 장점에 추가 하여 컨넥션이 변경 될 이슈가 없으므로 클라이언트 접속 동안 데이터를 계속 유지 할 수 있다.
단점 :
- 컨넥션 위치 관리 비용, 데이터 동기화 비용이 추가 된다.
예를 들어 게임 서버에 위치한 사용자가 아이템을 사용하게되면 게임 서버에 접속한 사용자의 데이터를 업데이트 해야 하기 때문에 공통기는 컴포넌트는 또다른 컨넥션이 어느 컴포넌트에 접속 중인지를 항상 파악하고 있어야 한다.
Posted by kukuta

댓글을 달아 주세요

#Day 3 - 채팅 시스템 트래픽이 너무 많이 발생해요!!!

책상에서 꾸벅꾸벅 졸고 있는데 다시 전화가 왔다.

전화 : "안녕하세요 시스템팀 김미영 팀장입니다. 어제 신규 패치된 채팅 서버가 추가 될때 마다 IDC 내부 트래픽 그래프가 기하급수적으로 상승하고 있습니다. 아직은 괜찮지만 이대로라면 조만간 최대 허용 트래픽을 초과 할것 같습니다. 확인 부탁 드립니다."

(읭?! 김미영 팀장 어디서 많이 듣던 이름인데...기분 탓이겠지..) 


이 사실을 팀장님께 보고 드리니 아무래도 어제 투입된 채팅 시스템의 브로드캐스팅이 이런 문제를 발생 원인인것 같다고 말씀하시며 팀장님의 생각을 설명 해주셨다.

팀장 : "머신당 수용가능 최대 인원을 1000이라고 가정해보자. 그리고 머신 대수를 M 이라는 변수로 대채 해보자. 사용자 한 명당 한 개의 메시지를 보낸다면 자신을 제외한 모든 채팅 서버에게 메시지를 보내야 하니까...1000 x (M-1) 의 메시지 트래픽이 한 대의 머신에서 발생하겠지? 그런데 이게 총 M 대의 서버에하고 모든 사용자가 동시 채팅 메시지를 보내는 경우 M x (1000 x (M -1)) 의 메시지 트래픽이 발생하게 되는거지. 이게 뭘 의미하는지 알겠니?"

나 : "...음...글쎄요..."

내가 쉽게 답을 하지 못하고 우물거리고 있자 팀장님은 아무 말씀도 하지 않고 담배를 하나 물며 기다리셨다.. 거의 반 개피가 타들어 갈무렵 갑자기 수식 중 한부분이 눈에 들어 왔다.

나 : "아... 위 식을 정리 해보면 1000*M^2 -1000*M 이 되는 군요..여기서 M이 제곱이니까 변수 M이 증가 할때 마다, 즉 서버 머신이 추가 될때 마다 그래프는 기하급수적으로 증가하는 거군요.."

팀장님은 이제 알겠냐는 듯한 웃음을 지으며 저 M의 차수를 줄일 수 있는 방법을 찾아 오라 하신다.

자리로 돌아와 지금의 문제점에 대해 곰곰히 생각해 보았다.

머신 대수를 나타내는 항에서 에서 제곱이 발생한다. 이런 구조라면 사용자가 늘어나 머신이  추가 된다면 트래픽 그래프는 다시 한번 더 기울기가 가파라진다. 원인은 브로드캐스팅이다. 서버간 메시지 전달에 브로드캐스팅 방식을 사용 하면서 전체 머신 만큼의 메시지 트래픽이 발생하고, 모든 머신에서 브로드캐스팅을 하고 있으므로 M^2이라는 항이 생긴 것이다.

그렇다면 브로드캐스팅을 하지 않는다면? 메시지 전달에 유니캐스팅을 사용한다면 최대 그래프의 증가는 제곱이 아니라 선형 그래프를 그릴 것이다. 대상 사용자가 접속해 있는 머신을 알 수만 있다면 해당 머신에 유니캐스팅으로 메시지를 전달하면 된다라는 결론이 났다. 그런데 어떡게 대상사용자가 접속해 있는 머신을 알아내는가가 문제 였다. 그래서 다음 두 가지 방법을 생각해 보았다.

 1. 아직 전달 대상 머신이 어디인지 모르는 경우 전체 채팅 머신을 대상으로 사용자를 찾는 메시지를 브로드캐스팅 한다. 사용자를 가지고 있는 머신에서 응답이 오면 다음 부터는 그 머신에만 메시지를 유니캐스팅 하는 방식.

 2. 사용자가 어느 머신에 접속해 있는지 매핑 테이블을 유지하는 센트럴 시스템을 추가하고 사용자가 채팅 시스템에 접속하면 이 센트럴 시스템에 아이디와 위치를 등록한다. 모든 채팅 메시지는 이 센트럴 시스템으로 보내지고, 센트럴 시스템은 사용자가 있는 경우 해당 머신으로 메시지를 릴레이 하는 방식.

1번 방식의 경우 일단 위치를 알아내고 난 다음 부터는 해당 머신으로 바로 메시지를 전달하므로 메시지 전달 트래픽이 1밖에 되지 않지만 최악의 경우 브로드캐스팅과 똑같은 비용이 든다는 단점이 있다. 예를 들자면 모든 사용자가 현재 접속하지 않은 사용자에게 계속 메시지를 보낸다거나, 채팅 시스템이 방금 시작해 아무런 위치 정보가 없는 시점에 사용자들이 채팅을 시작한다던가 하는 시나리오 말이다,

2번 방식은 센트럴 시스템에 메시지를 보내는 트래픽과 센트럴 시스템이 릴레이 하는 트래픽, 이렇게 매 메시지마다 2의 트래픽 비용이 발생하지만 최대 트래픽이 (1x1000+1x1000)xM 만큼으로 일정한 선형 그래프를 그린다는 장점이 있다.

1번과 2번 모두 각자의 장단점이 있긴하지만 나는 최악의 경우 트래픽이 선형 증가를 하는 시스템이 더 안정적이라고 판단 2번 방식을 택하기로 했다.

그래서 다음과 같은 디자인이 나왔다 :
 


팀장님이 트래픽 사용으로 회사에서 지불하는 비용도 무시할 수 없이 크므로 오늘 내로 패치를 해야 한다고 하신다.
오늘도 뜨는 아침 해를 보며 센트럴 시스템과 기존 채팅서버에 센트럴 서버와 통신하는 인터페이스를 완성 했다.

입사 삼 일째, 집에 가지 못한 시간도 삼일째..피곤하다..책상이 아닌 이불에서 자고 싶다...ㅠㅠ

[발로 그리는 분산 시스템] - 발로 그리는 분산 시스템 #Day 1 - 발로 그리는 채팅 시스템 
[발로 그리는 분산 시스템] - 발로 그리는 분산 시스템 #Day 2 - 채팅 서버에 접속이 안되요!!

Posted by kukuta

댓글을 달아 주세요

  1. BlogIcon 김경모 2012.02.20 23:34  댓글주소  수정/삭제  댓글쓰기

    아 지나가던 쪼그만한 학생입니다 ㅎㅎ.
    실제로 입사하자마자 시스템을 개발해라 하고서 (비록 채팅 서비스지만 ㅎㅎ...)
    오늘 안에 되겠니? 하고 하는 무서운 경우가...
    있을거라는 무서운 생각을 하면서 3일차까지 보고있습니다 ㅎㅎ.

    사내 에서 브로드 캐스팅을 하더라도 트래픽이 많이 발생하는군요 ㄷㄷㄷㄷ....
    역시 사람을 찾기위해서 그때 마다 서버를 찾기에는..... 무리가 따르죠 ㅎㅎ
    (물론 . 색인 작업을을위한 사용자를 알파벳 순(이름순)으로 정리해서 서버에 차곡 차곡 쌓을수있다는 무식한 생각도해보지만 ㅎㅎ..서버가 역시 효율적으로 유저관리를 하기가.. 알고리즘을 다시짜야하니 ㅎㅎ)

    센트롤 시스템을 통한 (사용자가 접속하고 나갈때마다 센트롤 테이블의 유저 테이블을 업데이트하면 ㅎ..)
    게 좋다고 생각이되네요 ㅎㅎ..
    사용자별로 n번 브로드 캐스팅을 한다면은

    1000명의 유저가 10개의 서버에있는 사용자를 찾기위해서는 ...
    최대10000 번의 메시지를보내야겠죠.... 물론... 첫 메시지에만 한정이 되겠지만 ㅎㅎ..
    엄청난 트래픽이.... n*m*1/2 의 복잡도란 ㄷㄷ

    하지만 두번째 방법은 첫메시지 2n의 시간 복잡도를 갖고 . 이후에 상대편이 나갔을때에만
    그유저가 있는 머신에 메시지를 보내서 다시 접속 확인을 할수있는 시스템이 구축...이 될라나요 ㅋㅋ앜...
    (수식은 틀렸지만 이게 효율적이라고 생각함니다 ㅎㅎ!!)

    물론 두번째 경우든 첫번때 경우든 메시지가 전송이 됬다는 ask 메시지나 확인 법
    그리고 그후에 유저를 다시 검색하고 이사람이 없다면은 접속이 실패했다는 메시지도 메시지를 전송한 사람에게 알려줘야하는 부담이있네요 ㅎㅎ.

    물론 리니지의 장사 채팅 같은 경우는 브로드 캐스트로 ^^.~!!

    괜히 니자가다가 주저리 주저리 해봄니다 ㅎㅎ..

    흥미 진진하고 재밌네요 ㅋㅋㅋ...

  2. Favicon of http://kukuta.tistory.com BlogIcon kukuta 2012.02.23 23:22  댓글주소  수정/삭제  댓글쓰기

    1번 방식은 사실 한번으로 끝나는 것이 아닙니다. 없는 사용자에 대해서 계속 검색을 하게 된다면 결국 지속적으로 브로드캐스팅을 하는 것이나 다름 없습니다. 최악의 경우를 고려한다면 브로드캐스팅 정도의 비용이 지불 됩니다.
    2번 경우엔 사용자 로긴과 로그아웃을 처리해주면 보낼 수 없는 사용자에 대한 처리도 보다 쉬워지지요.

    다만 여기서 빠진 이야기가 있는데 결국 센트럴 릴레이 서버가 병목이 될 수도 있습니다. 이에 대한 분산 정책도 나중에 다룰 예정입니다ㅎㅎ

    관심있게 지켜봐 주셔서 감사합니다.

    • BlogIcon 김경모 2012.02.27 13:17  댓글주소  수정/삭제

      아 ㅋㅋ
      중앙에서 처리해주는 중앙 릴레이 서버 녀석도 고려해야되는군요 이런 ㅋㅋ

      저도 안드로이드 메신저 서버에대해서 생각해보다가 수천만이나되는 ㄷㄷㄷ 유저에게 메시지를 보내는 대규모 메신저 서버에대해서 궁금했었거든요 ㄷㄷㄷㄷ ㅋㅋ 비슷할라나 ㅋㅋㅋ...앜 ㅋㅋㅋ

      곧 개강이니 ㅠㅠ 네트워크 교수님한테 물어봐야지요 ㅎㅎㅎ

      재밌게 보고감니다 ^^*

Day 2 - 채팅 서버에 접속이 안되요!!
채팅 서버를 실서버에 반영하고 피로에 지쳐 잠이 들었다. 전지현과 손예진이 서로 나랑 사귀겠다며 싸우는 꿈을 한참 꾸고 있는데 전화가 왔다. 여자다.
전화 : "안녕하세요. 운영팀 김미영 팀장입니다. 12시 부터 게임에 접속 할 수 없다는 메시지와 함께 클라이언트가 다운 되고 있습니다. 조속한 조치 부탁드립니다."

젠장..접속이 안된다니. 게임에 접속해 보니(처음으로 우리 회사 게임에 접속했다!!) 정말 게임에 접속 할 수 없다는 메시지와 함께 클라이언트가 다운된다. 클라이언트 개발자에게 디버깅을 문의하니 채팅 서버에서 더 이상 접속을 받을 수 없다는 에러 코드를 리턴한단다.

우리 게임 평균 동접이 1만인데 채팅 서버는 동접 1천 밖에 받지 못 했던 것이다. 급하게 시스템 팀에 연락해 채팅 서버 10대를 추가 하고 운영팀에 문제 상황이 해결 되었다고 응답해 주었다.

시스템이 정상 동작 하는지 모니터링 하다 나도 모르게 다시 잠이 들었다.

30분 정도 잠들었나 싶었을 무렵 다시 전화가 울린다.
전화 : "안녕하세요. 운영팀 김미영 팀장입니다. 접속 할 수 없다는 메시지는 더 이상 뜨지 않는데요. 사용자들간에 채팅이 되지 않는다고 합니다. 확인 부탁 드립니다."

읭? 채팅이 되지 않는다고? 다시 게임에 접속해 클라이언트 개발자와 테스트를 해봤다. 어라..? 잘 되는데? 접속을 끊고 다시 테스트 해보니 이번에는 되지 않는다!! 서버 로그를 살펴 보니 해당 사용자를 찾을 수 없다는 메시지다. 분명히 접속 중인데..아..다른 서버에 접속 중이었다. 내가 만든 채팅 서버는 서버간 메시지 전송 기능이 없던 것이었다.

팀장님이 원래 채팅 시스템은 없던 서비스였기 때문에 아직 사용하는 사람들이 그렇게 많지는 않다고 하시며 어서 패치 하라고 하신다. 그래서 다음과 같은 설계도를 그렸다.

채팅 메시지를 받고 로컬 머신에서 전달 대상을 찾지 못하면 전체 시스템으로 브로드캐스팅 하는 방식이다. 채팅 메시지를 받은 서버는 로컬에 있는 사용자면 메시지를 전달 하고, 사용자가 로컬에 없는 경우에는 메시지를 무시 한다. 
브로드캐스팅 기능만 추가 하는 것이기 때문에 금방 끝날 줄 알았는데 의외로 개발하는데 시간이 많이 걸렸다. 결국 다시 아침을 뜬 눈으로 맞았다.

간단한 테스트 후 시스템 팀에 연락하여 새로운 서버를 서비스에 반영했다. 이제 어떤 채팅 서버에 접속하던지 메시지를 못 받는 상황이 해결 되었다. 입사 이틀 째, 집에 가지 못한 시간도 이틀째..피곤하다..집에 가고 싶다..ㅠㅠ
 
[발로 그리는 분산 시스템] - 발로 그리는 분산 시스템 #Day 1 - 발로 그리는 채팅 시스템

Posted by kukuta

댓글을 달아 주세요

/**
한 대의 머신이 처리 할 수 있는 cpu 파워와 memory, kernel object에는 한계가 있고 이를 극복하기 위해 분산 시스템이라는 것을 구축한다. 이번 포스팅 시스즈에서는 connection 한계를 극복하는 방법과 그러기 위해 고려할 사항들을 생각 해보자.
*/
나는 대학을 졸업하자 마자 꿈에도 그리던 게임 업계에 취직했다. 직원이 채 10명도 안되는 작은 회사이긴 하지만 청년 실업 60만에 육박하는 이 사회에서 졸업과 동시에 취업이라니 얼마나 뿌듯한가!!
첫 출근하니 팀장이라는 분이 나를 맞아 주었다.
'우리 회사는 출시한 게임은 몇개 안되지만 그래도 최대 동접 네 자리를 자랑하는..' 주저리 주저리..뭔 말인지도 모를 회사 소개가 끝나고 팀원들 소개로 이어졌다..아니..그냥 팀원 소개였다..(지금 까지 PM 역할을 하는 팀장과 개발자 단 둘이서 게임을 만들어 왔다고 한다)..팀원은..남자 였다..(그냥 그랬다는 거다..)
자리를 배정 받고 앉아서 컴퓨터를 켜자 마자 팀장님이 자리로 오시더니 이번에 우리 게임에서 채팅 시스템이 추가 된다고 한다..(읭? 동접 네자리 게임이 채팅도 안된거야?!)..내가 만든 것이 바로 실 서비스 투입 될 거라고 하니 잘 만들어 달란다..아직 아무 것도 모르는 어리버리긴 하지만 입사 하자마자 뭔가 중요한 일을 맡은것 같아 기분이 좋다.
미션 1 : 채팅 시스템을 구축하라!!
팀장님이 개발하기 전에 먼저 시스템 설계를 하는 것이 좋다고 하며 자기가 검토해 줄테니 설계도를 그려 오라고 한다. 누가 봐도 알수 있도록 그리는 것이 포인트라고 한마디 덧붙여 주시는 것도 잊지 않으셨다.
그렇지 학교 다닐 때 항상 아무런 생각 없이 코드 부터 먼저 짜다 엎었던 적이 한두번이 아니었지..
진중한 마음으로 설계에 대해서 고민하기 시작 했다. 

# Day 1 - 발로 그리는 채팅 시스템 하루 종일 채팅 시스템을 어떻게 만들어야 하나 고민 하다 아래와 같은 설계도를 만들었다. 센스 있게 'ㅋ'도 넣었다. 팀장님이 보시면 좋아 하실것 같다 :-)

설계도를 팀장님께 보여드리니 아무말 없이 설계도만 보고 계신다. 읭?! 저 쉬운 설계도가 이해가 안 가시나? 누가 봐도 알수 있도록 엄청 직관적으로 그린건데..
한참을 들여만 보시더니 갑자기 긴 한숨과 함께 담배를 입에 무시며 오늘 까지 만들 수 있겠냐고 하신다..
자신 있게 '네!' 라고 대답하니 그럼 이대로 개발 하란다. 역시 한번에 통과 했다. 후딱 후딱 빨리 빨리 만들고 퇴근하자!!라고 했지만 채팅 서버 하나 만드는데도 하루가 꼬박 걸렸다. 아...해뜬다...집에 가고 싶다...


[발로 그리는 분산 시스템] - 발로 그리는 분산 시스템 #Day 2 - 채팅 서버에 접속이 안되요!!
Posted by kukuta

댓글을 달아 주세요

  1. 2012.02.17 16:44  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

    • Favicon of https://kukuta.tistory.com BlogIcon kukuta 2012.02.20 00:32 신고  댓글주소  수정/삭제

      발로 그리는 분산 시스템은 시간이 나는 대로 짬짬이 계속 연재 할 생각 입니다. 가끔 들려 주셔서 부족한 부분이 있으면 조언 부탁 드릴게요.

/**
 오래간만에 휴가 기간이다. 아무런 생각도 하지말고 '분산 시스템'이라는 주제에 대해 포스팅을 시작해 보자.
*/ 

분산 시스템(Distributed System)?
분산 시스템의 교과서 적인 Distributed System Concepts (Andrew S. Tanenbaum) 의 말을 빌리자면
 "하나의 시스템 처럼 보이는 독립된 컴퓨터들의 집합"
 (A distributed system is a collection of independent computers that appears to its users as a sigle coherent system)
이라고 정의하고 있다.

위의 정의를 두 가지 주요한 관점으로 바라 볼 수 있다. 한가지는 하드웨어 - 독립되어 자율적으로 돌아가는 하드웨어 머신, 다른 한 가지는 소프트웨어 - 유저 관점에서 보았을 때 마치 하나의 시스템으로 여겨지는 시스템. 위 두가지 사항은 분산 시스템을 구성하는 핵심적인 요소이며 시스템을 디자인 할 때 절대 잊어서는 안되는 원칙이다.

위 두 가지 대 원칙을 가지고 분산 시스템을 디자인 할 때, 다시 아래의 생각들을 해봐야 한다.
 - 다양한 컴퓨터(or 장비)들 사이에 다양한 통신 방법들을 어떻게 사용자로 부터 숨길 것인가?
 - 어떻게 사용자와 시스템 간의 일관적이고 단일화된 커뮤니케이션 통로만들 것인가?

지금 까지 컴퓨터 네트워크의 발전사를 살펴 보면 다양한 커뮤니케이션 방법, 컴퓨터의 종류, 통신 장비들을 이용하기 위해서 레이어(Layer)를 두고 각 레이어마다 프로토콜을 정해 사용자에겐 자신이 직접적으로 닿고 있는 레이어만 신경쓰면 얼마든지 시스템에 접근 할 수 있도록 하는 형태로 발전해 왔다.  예를 들자면 OSI 7 layer, TCP/IP 와 같은 것들이 있다.

위와 같은 레이어링은 하드웨어 뿐만 아니라 소프트웨어 디자인에도 상당한 도움이 된다는 사실을 기억하자.

분산 시스템의 목적?
그렇다면 왜 유저 관점에서 하나 처럼 보이지만 뒤에서는 여러 다양한 컴퓨터들로 구성되어 있는 복잡 다단한 분산시스템이라는 것을 만들어야 하는 것일까?

내가 생각하는 가장 첫번째 이유는 자원의 부족 때문이다. 여기서 말하는 '자원'이라는 것에는 컴퓨터의 CPU 파워, 메모리, 하드 디스크 스토리지 등등 우리가 사용하는 모든 컴퓨터의 자원을 의미한다. 요즘 같은 서버-클라이언트 구조의 서비스들이 점점 더 발달할 수록 더 많은 자원을 요구하게 되고, 머신 한 대로 처리 할 수 있는 양에는 한계가 있다. 그래서 우리는 분산 시스템을 도입하여 위의 문제를 해결한다.

두 번째는, 장애시 대처다. 단일 머신에서 돌아가는 시스템이라면 해당 머신의 수명이 다하거나 어떠한 불의의 사고로 다운이 되게 된다면 모든 시스템이 다운되게 된다. 하지만 여러 대의 머신이 분산하여 연산을 처리하고 데이터를 저장하고 있다면 한대의 장애가 전체 시스템의 장애로 이어지지는 않는다. 이를 위해서도 분산 시스템은 필요하다.

셋 째, 사용자에게 자원 접근의 편리성을 제공하기 위해서다. 사용자는 많은 종류의 다양한 자원들에 접근을 요구한다. 이때 사용자에게 일관적이고 단일화된 방식으로 사용자가 원하는 자원에 쉽게 접근하게 할 수 있는 것이 바로 분산 시스템이다. 예를 들어서 특정 인터넷 페이지가 있다고 가정해 보자. 우리는 이 페이지를 저장하고 있는 서버가 어디에 있으며 아이피가 무엇인지 알지 못한다. 하지만 인터넷 브라우저에 url을 입력하면 우리가 원하는 사이트에 접속하고, 우리가 원하는 정보를 얻을 수 있다. 여기서 url은 단일화된 자원 접근 방법이고, 앞에서도 말했다 싶이 사용자는 이 자원이 실제 세계 어떤 서버에 있는지에 대한 고민은 전혀 하지 않아도 된다.

위와 같은 특성들을 통틀어 투명성(Transparency)라고 한다.
사용자는 어디에 어떤 자원이 어떻게 저장되어 있는지 알필요 없고, 몇 대의 시스템이 어떻게 구성되어 돌아가는지 알 필요가 없다. 이런 투명성은 아래와 같이 여덟가지 항목에 적용해 볼수 있다.
 - Access : 데이터 표현 방식, 자원에 접근 방법을 사용자에게 숨긴다.
 - Location : 자원이 어디에 위치하고 있는지 사용자에게 숨긴다.
 - Migration : 자원의 이동을 사용자에게 숨긴다(이동하더라도 동일한 방법으로 접근 할 수 있음을 의미한다)
 - Relocation : 사용자가 사용 중임에도 자원이 이동 할 수 있다. 하지만 이 사실을 사용자에게 숨긴다.
 - Replication : 자원은 복사 될 수 있다. 하지만 사용자는 자기가 복사본에 접근하는지, 원본에 접근하는지 모른다.
 - Concurrency : 접근 자원이 다른 사용자와 함께 공유되고 있어도 사용자는 모른다.
 - Persistance : 자원이 메모리에 있든, 하드디스크에 있든 사용자는 모른다.

위와 같은 투명성을 제공하여 머신 자원 부족과 장애 대처, 사용자에게 자원에 대한 접근 편리성을 제공하는 것이 분산 시스템의 목적이라고 할 수 있겠다.

..라고 책을 보고 나름 생각한 것을 주장한 것이라 꼭 이게 맞다고는 말 못하겠다...;;

 
Posted by kukuta

댓글을 달아 주세요

  1. ㅇㅇ 2017.06.15 22:04  댓글주소  수정/삭제  댓글쓰기

    분산컴퓨터의 목적 중 3번째는 장점이 아니라 구현할때 고려해야하는 점 아닌가요?

    • kukuta 2017.06.23 09:27  댓글주소  수정/삭제

      ㅇㅇ님께서 언급하셨듯이..
      장점이 아니라 분산컴퓨팅의 목적입니다.

이전에 Lamport algoritim(http://kukuta.tistory.com/105)과 알고리즘에 사용되는 개념에 대해 알아 본적이 있다. 오늘은 좀 더 심화된 과정으로써 Lamport 알고리즘을 이용하는 Totally Ordered Multicasting에 대해서 알아보도록 하겠다.

Totally Ordered Multicasting이란?
Totally Ordered Multicasting이란 "모든 프로세스가 바라 보는 모든 메시지(이벤트)의 순서가 동일함을 보장"하는 멀티캐스팅 방법이다. 그리고 여기에 우리가 이전에 공부했던 Lamport 알고리즘이 사용될 수 있다.

왜 필요 한가?
먼저 왜 이런 멀티 캐스팅이 필요한지 예를 살펴 보자 :

전국에 걸친 지점을 가진 어떤 은행이 있다. 전국에 여러 개의 DB를 설치 해두고 각 지점은 가장 가까운 DB를 이용하여 업무를 처리한다. 각 DB는 업데이트 될 때마다 다른 지역에 있는 DB에 업데이트 이벤트를 복사해 데이터 동일성을 유지하고 있다. 이 때,

고객이 서울지점에서 1000원이 들어 있는 자신의 계좌에 100원을 입금하려 하고, 부산에 있는 은행 본점은 이 계좌에 1%의 이자를 주려고 했다.

서울 지점 은행은 1000원에 100원을 입금 한 후 1%이자 지급 메시지를 받아 1111원의 잔고를 가지게 되었다.
부산 본점 은행은 1000원에 1%이자를 지급한 후 100원을 입급했다는 메시지를 받아 1110원의 잔고를 가지게 되었다.

위의 예에서 처럼 순서가 꼬이면 서로 다른 결과를 가지게 되는 일이 종종 있다. 하지만 여기서 한가지 또 주목 할 것은 실제 시간에서 어떤 이벤트가 먼저 일어 났는지는 그렇게 중요하지 않다는 것이다. 고객의 입금이 먼저 처리 되든, 은행의 이자 지급이 먼저 처리 되든, 양쪽에서 동일한 순서로 처리 되면 되는 것이지 입금이 먼저 처리 되어야 한다, 이자 지급이 먼저 처리 되어야 한다라는 이슈는 없는 것이다(실제 은행 입장에서 보면 이자를 먼저 지급하는게 더 이익일 수 있지만 그런 문제는 은행장이 되면 생각 하도록 하자).

위와 같은 예에서 해답으로 사용 할 수 있는 것이 바로 Totally Ordered Multicasting 이며, 그 것을 구현하기 위해 이용 될 수 있는 것이 Lamport algoritim 이다.

어떻게 구현 되는가?
기본적으로 Totally Ordered Multicasting 은 멀티캐스팅이다. 그래서 아래와 같은 속성을 갖는다 :
  1) 모든 프로세스는 멀티캐스팅 그룹에 있는 다른 모든 프로세스의 존재를 알아야 한다.
  2) 송신자가 전송하는 메시지는 송신자 자신에게도 전달 되어야 한다.

그리고 추가적으로 메시지는 전송 중에 순서가 꼬이지 않는 것을 보장해야만 한다(그래서 보통 TCP를 사용한다).

Totally Ordered Multicasting에서 송신자는 :
  1) 모든 메시지에 timestamp를 찍어서 전송한다.

수신자는 :
  1) 메시지가 수신되면 local queue에 메시지를 저장한다(timestamp에 따른 순서로 정렬 되어야 한다).
  2) 저장 후 멀티캐스팅 그룹 내에 있는 모든 프로세스들에게 ack를 리턴해야 한다(자기 자신도 포함).
  3) 단, ack 메시지에도 timestamp가 찍혀야 하며, 송신자가 보낸 timestamp보다 커야 한다(Lamport 알고리즘에 따라 clock도 앞으로 당겨 주어야 한다).

위와 같은 과정을 거쳐 모든 프로세스들로 부터 ack를 받고 queue에 가장 앞에 있는 메시지라면 현재 그룹 내에서 돌아 다니는 메시지 중에서 가장 timestamp가 빠른 메시지 임이 보장 된다.

아래 그림을 보면서 과정을 정리 해 보도록하자(괄호안의 숫자는 타임 스탬프를 의미한다).

[그림 1] Totall Ordered Multicasting

[그림 1] Totall Ordered Multicasting


  1. 1번에서 프로세스 A는 타임 스탬프가 10일 때 프로세스 B에게 메시지(Msg A)를 보낸다. 
     (기본 개념은 자기 자신에게도 동일한 메시지를 보내고, 그것을 수신하여 로컬 큐에 저장하는 것이지만,  편의상 보내면 받은 것으로 생각하고 바로 로컬 큐에 넣도록 하자)

    이렇게 되면 프로세스 A의 로컬 큐에는 Msg A(t:10) 가 아직 아무런 ACK도 받지 못한 상태로 저장 되게 된다. 다시 한번 말하지만 로컬 큐에서 빠져 나가기 위해서는 큐의 가장 앞에 있을 것이며, 모든 프로세스들로 부터 ACK를 받아야 만한다.
  2. 2번에서 프로세스 A는 자기 자신에게 ACK를 보낸다. 이로써 프로세스 A의 로컬 큐에는 Msg A(t:10) 가 A로 부터 ACK를 받은 상태로 저장 된다.
  3. 지금 부터 중요하다. 3, 4, 5 번 같이 보도록 하자. 3번은 Totally Ordered Multicasting이 실패 하는 경우를 가정 하고 있다. 

    프로세스 B가 보낸 Ack A가 3번과 같이 Msg B보다 순서가 꼬여 먼저 도착하는 것은 애초에 멀티캐스팅의 제약 조건에 걸린다. 저런식으로 메시지가 꼬일 수 있다면 뭘 해도 안된다.

    5번과 같이 Msg B 보다 늦게 도착 한다면, 로컬 큐의 가장 앞에는 Msg B가 자리 잡고 있기 때문에, 프로세스 A의 Ack가 완료 되더라고 큐에서 빠져 나가지 못하고 Msg B가 완료 될 때 까지 대기 상태가 된다.

    만일 Ack A가 Msg B 보다 먼저 도착하려면 프로세스 B에서 Msg B보다 먼저 보내야 하는데 Ack A 이후에 보내진다는 것은 프로세스 A의 타임스탬프에의해 프로세스 B의 로컬 타임스탬프가 이미 조정 되었음을 의미하므로 큐에 저장될 때 Msg A는 Msg B보다 앞에 정렬 되게 된다.

이런 식으로 각 프로세스는 도착하는 메시지들을 정렬하며, 모든 프로세스가 처리하는 메시지의 순서는 같아지게 된다.

Ref :
 - Distributed Systems - priciples and paradigms(Andrew S. Tanenbaum, Maarten van Steen)
 - [진리는어디에] - Logical clock

Posted by kukuta

댓글을 달아 주세요

용도 : 분산 시스템에서 특정 1개 프로세스를 coordinator로 지정하는 알고리즘
원리 : 각 프로세스들에게 고유한 아이디를 부여하고, 가장 큰 아이디를 가진 프로세스가 항상 coordinator 역할을 하도록 한다.

장점 :
 * 여러 개의 분산된 (서버)프로세스 중 coordinator 역할을 할 프로세스를 동적으로 선정 할 수 있다.
 * Coordinator (서버)프로세스 장애시 설정의 변경, 시스템 재시작 필요 없이 다른 프로세스가 해당 역할을 넘겨 받
   을 수 있다.

단점 :
  * 동적인 시스템 확장이 힘들다. 그룹내 모든 프로세스들은 다른 프로세스들의 정보를 미리 알고 있어야 하므로 
    신규 머신 추가를 위해서는 설정 파일을 변경하고 재시

제약 사항 :
 * 각 프로세스들은 고유한 아이디(라던지 순차적으로 구분 할 수 있는 무엇인가)를 가지고 있어야 한다.
 * 모든 프로세스들은 몇 개의 다른 프로세스가 있는지 알아야 한다.
 * 하지만 다른 프로세스가 현재 구동 중인지 아닌지는 알 필요 없다.


구동 방식 :
 a1. 그룹 내의 프로세스 중 하나가 coordinator가 다운 되었다는 것을 인지
   (그림에서는 4번 프로세스가 7번 프로세스가 다운 된 것을 발견 했다)
 a2. coordinator의 다운을 감지한 프로세스는 자기보다 높은 아이디를 가지고 있는 프로세스들에게 ELECTION 메시 
 a3. 아무런 프로세스도 응답을 하지 않으면 그 자신이 coordinator가 된다.

 b-d. ELECTION 메시지를 받은 프로세스들은 sender에게 OK 메시지를 전송하고, sender의 역할을 이어 받는다.
   (그림에서는 b에서 5번과 6번 프로세스가 4번에게 OK 메시지를 전송하고,  c에서 5번 프로세스가 4번 프로세스
    처럼 6번과 7번에게 ELECTION 메시지를 보낸다. 그리고 6번 프로세스역시 이전의 5번 프로세스가 4번 프로세스
    에게 했던것 처럼 5번에게 OK 메시지를 보낸다.)

 e. 가장 마지막 까지 election에 참가한 프로세스는 자신이 coordinator가 됨을 확인하고, 다른 모든 프로세스들에게
   새로운 coordinator의 등장을 알린다.
   만일 이전에 죽었던 프로세스가 다시 살아 나는 경우(7번 프로세스가 재부팅 되는 경우), 해당 프로세스는 위의
   과정을 거쳐 다시 coordinator가 된다.
Posted by kukuta

댓글을 달아 주세요

  1. Favicon of http://sdadsa BlogIcon sadsda 2010.08.12 13:57  댓글주소  수정/삭제  댓글쓰기

    http://maplestory.nexon.com/MapleStory/Page/Gnx.aspx?URL=home/index&DeployAID=8959854&DeployWID=4&DeployCID=5641586

일반적으로 스켈레톤이 reference count 대신 자신을 가리키는 프록시의 reference list를 유지한다. Reference list는 다음과 같은 특징들을 가진다 :

  • Reference list가 이미 프록시에 대한 정보를 가지고 있다면 프록시 정보 추가 요청에 대해 아무런 오퍼레이션도 하지 않는다.
  • Reference list에 프록시에 대한 정보가 없다면 프록시 정보 삭제 요청에 대해 아무런 오퍼레이션도 하지 않는다.
  • 위와 같은 특성을 idempotent하다고 하며, 한글로는 '멱등'의 뜻을 가지고 있다.

Reference list의 경우에는 신뢰성이 없는 분산시스템에서 사용하기 적합하며 이유는 아래에서 살펴보도록 하자.

Create
프로세스 p가 객체 o에 대한 remote reference를 만들면, 정상적으로 등록되었다는 응답이 올 때까지 계속 프로세스 p의 identification을 등록 요청하는 메시지를 전송한다. 그리고 삭제도 위와 비슷하다. 결과적으로 신뢰성이 없는 분산시스템에서 사용하기 적합하며, 중복 메시지에 대한 체크가 필요 없다. 이와 같은 reference list방식은 Java RMI에서 사용되고 있다.

Copy
프로세스 p1에서 p2로 레퍼런스를 복사한다면 :
  • p2는 객체 o의 스켈레톤에게 지속적으로 reference list에 등록 할 것을 요청
  • Ack가 도착하면 p2는 자신의 메모리 영역에 프록시를 생성한다.

Problem
프로세스 p1이 p2가 객체 o에게 레퍼런스 추가 요청을 하기 전에 자신의 레퍼런스를 삭제할 때 문제가 발생한다.

장점
비신뢰 분산시스템에서 failuer에 강하다. 스켈레톤은 주기적으로 프록시가 살아있는지 체크하는 ping을 보내고, 몇 번 시도후에 응답이 없으면 reference list에서 삭제한다.

단점
확장성에 안 좋음. 이것을 해결하기 위해 스켈레톤은 한정된 시간동안만 레퍼런스를 유지하고, 시간내에 갱신되지 않으면 reference list에서 삭제한다.

'진리는어디에' 카테고리의 다른 글

DrawPrimitive와 DrawPrimitiveUP의 차이  (1) 2008.05.19
[PHP]Fatal error: Maximum execution time of 30 seconds  (0) 2008.05.19
Reference list  (0) 2008.05.16
Generation reference counting  (0) 2008.05.15
Logical clock  (2) 2008.05.02
BTree  (8) 2008.03.26
Posted by kukuta

댓글을 달아 주세요

GRC(Generation reference counting)에 대해서 설명하기 전에 분산 시스템에서의 객체는 레퍼런스를 통해 접근되며, 객체쪽에는 객체를 대신하는 스켈레톤이, 레퍼런스 쪽에는 프록시가 있으며, 이 둘은 항상(proxy, skeleton) 짝을 이룬다는 것을 기억해 보자.

GRC에서 프록시는 그 자신이 몇 번이나 복사 되었는지에 대한 카피 카운터(이하 count)와 몇 번째 세대인지(몇 번째로 복사 된 레퍼런스 인지)를 나타내는 generation number(이하 generation)을 가지고 있다. 스켈레톤은 추후 generation과 count에 대한 정보를 유지할 테이블 G를 가지고 있다.

1. Initialze
객체 o가 프로세스 P에 생성 되면, o의 레퍼런스 p는 :
    p.genration := 0
    p.count := 0
으로, o에서 유지하는 테이블 G는 :
    o.G[0] := 1
    o.G[i] := 0, for all i >= 1
로 초기화 된다. 이 때 테이블 G는 레퍼런스의 복사에는 관여하지 않고, 레퍼런스의 삭제시에만 테이블을 조절하므로써 증가 오퍼레이션과 감소 오퍼레이션에 대한 레이스컨디션을 방지 할 수 있다.
 
2. Copy
레퍼런스 p가 q로 복사 되는 경우, q는 아래와 같이 초기화 된다 :
    q.generation := p.generation + I
    q.count := 0
그리고 p.count는 증기 한다 :
    p. count := p.count + 1

3. Delete
레퍼런스 p가 제거되는 경우, p는 객체 o의 스켈레톤에게 p.generation과 p.count를 담은 delete 메시지를 전송한다. 스켈레톤에서 삭제 메지시를 받으면 :
    o.G[p.generation] := o.G[p.generation] - 1
    o.G[p.generation + 1] := o.G[p.generation + 1] + p.count
가 되며 테이블 G의 모든 엘리먼트가 0이 되면(for all i >= 0, o.ledger[i] = 0) 객체 o는 삭제 된다.

'진리는어디에' 카테고리의 다른 글

[PHP]Fatal error: Maximum execution time of 30 seconds  (0) 2008.05.19
Reference list  (0) 2008.05.16
Generation reference counting  (0) 2008.05.15
Logical clock  (2) 2008.05.02
BTree  (8) 2008.03.26
Python embedding 1 - Overview  (6) 2008.03.13
Posted by kukuta

댓글을 달아 주세요

실세계에서 완벽한 동기화란 없다. 아무리 짧은 시간을 주기로 동기화를 시도해도 결국 네트워크 지연이나 기타등등의 여러가지 이유로 아주 근소한 차이라도 오차는 있기 마련이다.
해서 나온것이 'Logical clock'라는 개념이다. Locgical clock에서 중요하게 생각하는 것은 각 이벤트 간의 인과관계다. 즉 사건 A가 사건 B보다 먼저 발생했다는 것만이 중요한 것이지, 사건 A가 B보다 얼마나 빨리 발생 했느냐 같은 것은 고려 대상이 아니다.
예를 들어서 프로세스 P1가 메시지를 보내고 프로세스 P2가 그 메시지를 받았다고 가정하자. P1가 1이라는 시간에 메시지를 보냈다면 P2가 메시지를 받는 시간은 어쨋거나 1보다만 크면 된다. 2가 됐든 100이 됐든 그것은 중요한 것이 아니라 1의 시간 보다 뒤에 발생 했다는 사실만 증명 할 수 있다면 그것으로 OK다.

위에서 Logical clock이란 인과관계에만 관심을 가진다고 이야기 했다. 그렇다면 아무런 관련이 없는 경우라는 것은 무엇인가 설명 해보도록 하겠다. 두 개의 프로세스 P1, P2가 존재하긴 하지만 서로 아무런 메시지도 교환하지 않고 묵묵히 자기와 관련된 이벤트들만 발생시키고, 수행한다고 가정하자. Logical clock관점에서는 이런 아무런 상관관계가 없는 이벤트들을 'concurrent'하다고 한다. 이런 이벤트들은 동기화 대상이 아니라 그냥 자기 갈길 가도록 내버려 두면 된다. 아무런 메시지 교환도 없는데 굳이 거기다가 동기화를 맞춰줄 필요는 없는 것이다.

지금까지 다소 길게 Logical clock라는 것의 개념에 대해서 설명했다. 그럼 지금부터는 어떻게 하면 이런 logical clock를 구현 할 수 있는지 살펴보도록 하자.

Lamport timestamp
Lamport 알고리즘은 Lesile Lamport라는 사람에 의해 발명된 간단한 logical clock 알고리즘 이다. 이 알고리즘은 사건의 발생 순서를 수자로 나열할 수 있다는 개념에서 부터 출발하여 아래의 간단한 몇가지 룰을 따른다 :
  1. clock counter는 각 이벤트가 발생하기 전에 증가한다.
  2. 프로세스가 메시지를 보낼 때, 메시지에 clock counter 값을 같이 보낸다.
  3. 메시지가 도착하면 받은 clock counter와 자신이 가지고 있던 clock counter를 비교하여 자신이 가진 것이 크다면 그대로 유지하고, 새로 도착한 것이 더 크다면 새로운 clock counter에 1을 증가시킨 것을 자신의 clock couter로 셋팅한다.
참고적으로 하나의 프로세스에서 동일한 시간에 두개의 이벤트가 발생헤서는 안된다. 그래서 아래와 같은 조치가 필요하다 :
  • 하나의 프로세스에서 두 개의 사건이 발생하는 간격이 tick이 터지는 간격보다 더 빠르다면, 시간 구분을 할 수 없고 인과관계가 엉망이 된다. Tick의 발생 주기는 이벤트의 발생 주기보다 짧아야 한다.
  • 두개의 프로세스에서 동일한 시간에 이벤트를 발생 시켜버린다면 역시 시간 구분을 할 수 없고 인과관계가 엉망이 되어버린다. 그래서 모든 시간의 소수점 이하로 프로세스의 번호를 붙여 다른 프로세스에서 같은 시간을 발생 시킬 수 없도록 한다.

백문이 불여일견이라고 자잘한 설명을 나열하는 것 보다 그림과 함께 하는 예제를 한번 보도록 하자 :

사용자 삽입 이미지

왼쪽 부터 프로세스 0, 1, 2라고 생각하자. 각 프로세스는 서로 다른 머신에서 돌아가고 있고 서로 다른 tick 주기를 가지고 있다. 뭐 거의 비슷하긴 하겠지만 조금 다르다고 생각하자.

프로세스 0번에서 6에 프로세스 1번으로 메시지를 보냈다. 프로세스1번이 메시지를 받은 시간은 16이므로 총 10이라는 시간이 걸렸다. 하지만 시간이 얼마나 걸리건 우리가 관심있어하는 것은 그것이 아니고 그저 메시지를 받는 행동이 보내는 행동보다 더 늦게 일어났다는 것에 주목하자.
위와 비슷하게 프로세스1번은 프로세스2번에게 메시지를 보낸다. 24에 보냈고 40에 도착했다. 여기까지는 아주 정상적인 과정이다. 일찍 보냈고 그 보다 늦게 받았다.

지만 세 번째 메시지에서 문제가 발생하는데 프로세스2번에서 60에 전송된 메시지가 프로세스1번에 56에 도착했다. 이전에 발생한 이벤트의 시간이 이 후에 발생한 이벤트의 시간보다 크다. 논리적으로 뭔가가 잘 못된 것이다.
이 때 동기화(synchronization)과정이 일어난다. 동기화 과정이라고 해서 크게 어려운건 아니다. 도착한 메시지의 clock counter가 자신이 가진 것 보다 더 크다면, 도착한 clock counter에 1을 더한값을 자신의 clock counter를 수정하는 것 뿐이다.

Link :
 - Lamport 알고리즘을 이용한 Total Ordered Multicasting : http://kukuta.tistory.com/143

'진리는어디에' 카테고리의 다른 글

Reference list  (0) 2008.05.16
Generation reference counting  (0) 2008.05.15
Logical clock  (2) 2008.05.02
BTree  (8) 2008.03.26
Python embedding 1 - Overview  (6) 2008.03.13
파이썬으로 utf-8 문서 읽기  (1) 2008.02.22
Posted by kukuta

댓글을 달아 주세요

  1. Favicon of http://blog.naver.com/stallon72 BlogIcon 홍성봉 2008.05.14 17:34  댓글주소  수정/삭제  댓글쓰기

    정리를 잘 해놓으셔서 내용 퍼갑니다. 대단히 감사합니다.