2011-08-02 4 views
14

서버 구성 요소가 완전히 erlang으로 작성된 기존 (게임) 프로젝트에 들어갈 예정입니다. 때로는이 시스템에서 데이터 조각을 얻는 것이 너무나 어려울 수 있습니다 (플레이어 56가 얼마나 많은 위젯을 소유하고 있는지 관심이 있습니다). 데이터를 소유 한 프로세스를 찾을 수 있다고 가정하면 해당 프로세스에 메시지를 전달하고 메시지를 다시 전달할 때까지 기다릴 수 있지만 여러 대의 시스템으로 확장되지 않고 응답 시간이 지연됩니다.Erlang ETS 테이블 대 메시지 전달 : 최적화 관련 문제?

저는이 게임에 존재하는 많은 작업을 여러 프로세스에서 자주 액세스하는 정보가 보호 된 ets 테이블에 저장되는 시스템으로 대체하는 것을 고려해 왔습니다. 테이블의 소유자는 아무것도하지 않고 업데이트 메시지를받습니다 (플레이어는 방금 5 개의 위젯을 사용했습니다). 그에 따라 테이블을 업데이트합니다. 모든 예외를 catch하고 다음 업데이트 메시지로 넘어갑니다. 플레이어가 거짓말 쟁이를 구입할 수있는 충분한 위젯을 가지고 있는지 알고 싶었던 모든 프로세스는 테이블을 들여다보기 만하면됩니다. (예, 위젯의 수를 줄이는 메시지가 버퍼에있을 수 있음을 이해합니다. 그러나이 문제는 통제하에 있습니다.)

내 질문에 대한 질문이 적고 요청이 많지 않습니다. 댓글. 나는 도움이되고 충분히 설명되거나 언급 된 어떤 것도 upvote 할 것이다.

이러한 구현의 단점은 무엇입니까? 나는 한 작가 - 다중 독자를 가질 때 볼 수있는 잠금 경합의 세부 사항, 여러 대의 컴퓨터에 배포 할 때 어떤 문제가 있는지, 특히 다음과 같은 사항에 관심이 있습니다. 이 전에.

답변

4

언제든지 발생할 수있는 일들이 많은 것처럼 들리지만 안전하고 일관된 방식으로 데이터를 집계해야합니다. Generic Event 동작을 살펴보십시오. 이 기능을 사용하여 이벤트 서버를 작성하고 이벤트를 통해이 모든 정보를 서버에 공유하도록 권장합니다.이 시점에서 ETS 테이블과 같이 어딘가에 로그하거나 저장하도록 선택할 수 있습니다. 제쳐두고, ETS 테이블은 플레이어가 가지고있는 "위젯"수와 같은 일관된 데이터에는 적합하지 않습니다. Mnesia 또는 우수 충돌 전용 데이터베이스 (예 : CouchDB)를 고려하십시오. 이 두 가지 모두 컴퓨터에서 매우 잘 복제됩니다.


자물쇠 경합이 발생합니다. 자물쇠가 없어야합니다. 메시지는 각 프로세스가 수신 할 때 동기 순서로 처리됩니다. 실제로 언어에 내장 된 메시지 전달 구문의 전체 요점은 공유 상태 동시성을 피하는 것입니다.
요약하면 일반적으로 메시지는 프로세스와 프로세스간에 통신합니다. 이것은 당신이 털이 있습니다. 왜냐하면 당신은 그 곳곳에 흩어져있는 프로세스로부터 정보를 필요로하기 때문에, 제 제안은 원래의 프로세스 외부에서 "흥미로운"모든 정보를 단일 실시간 소스에 집중시키는 아이디어를 기반으로합니다. .

+1

잠금 경합 질문은 erlang의 ets 테이블 구현과 관련됩니다. 테이블을 읽을 수있는 2500 개의 프로세스와이 프로세스에 쓸 수있는 프로세스가 있다면 결국 독자와 작성자가 동일한 데이터를 참조하려고 할 때가 있습니다. 그러면 그 문제를 해결해야합니다. 나는 분명히 수동으로 데이터 잠금과 잠금 해제를 시작하지 않을 것입니다. 가능한 경우 데이터의 불변성을 고려해 볼 때 확실하지 않습니다. – Sniggerfardimungus

7

기본적으로 ETS의 기본 동작은 일관성이 있습니다 (문서 : Erlang ETS 참조). 동일한 기능에서 수행되는 경우 원 자성 및 격리 기능을 제공하고 여러 업데이트/읽기 기능을 제공합니다. Erlang에서는 함수 호출이 축소와 거의 동일하므로 Erlang 측정 단위는 프로세스 간 시간을 공유하는 데 사용되므로 다중 함수 가능한 경쟁 조건을 만드는 더 많은 부분에서 ETS 작업을 분할 할 수 있습니다.

다중 노드 ETS 아키텍처에 관심이 있다면 ETS와 함께 OOTB 다중 노드 동시성을 원할 경우 아마도 기억 상실을 고려해야합니다. Mnesia. (힌트 : ram_copies 테이블, add_table_copy 및 change_config 메소드에 대해 구체적으로 말하고 있습니다.)

그 말은, 프로세스에 문제가 있다는 것을 이해하지 못합니다 (아마도 ets 테이블이 아닌 것으로 백업 됨). 나는 더 잘 설명한다. 프로젝트의 주된 문제는 첫 번째, 기본 가정이다. 간단합니다. 단 하나의 글쓰기 과정이 없습니다!

플레이어가 개체를 가져 와서 플레이어를 때릴 때마다 게임 상태를 업데이트하는 비 부작용없는 기능을 호출하므로 게임 상태를 관리하는 단일 프로세스가 있어도 다른 플레이어 클라이언트 '이봐, 그 물건 기억 나니? 그냥 잊어 버려! '; 이것이 멀티 플레이어 게임의 주된 문제가 지연되는 이유입니다 : 네트워크가 주요 문제가 아닌 지연은 보내기/받기 루틴을 차단하기 때문에 여러 번 있습니다.

영구적 인 테이블, 프로세스 사전 (BAD !!!) 등을 사용하여 ETS 테이블을 직접 사용하는 것은 객체 지향과 같은 동기화 문제를 고려해야하기 때문에 똑같습니다. 공유 메모리 (Java, everyone?)를 사용하는 프로그래밍 언어.

결국 응용 프로그램 개발과 관련된 단점은 일관성을 고려해야합니다. 일관된 응용 프로그램을 개발 한 후에 만 ​​성능 튜닝에 관심을 가져야합니다.

희망 하시겠습니까?

참고 : 나는 비슷한 것을 이야기하고 있다고 생각했기 때문에 MMORPG 서버와 같은 것에 대해 이야기했습니다.

6

ETS 테이블을 사용하면 문제가 해결되지 않습니다. 플레이어 위젯 수를 얻거나 설정하려는 코드는 항상 프로세스에서 실행되며 데이터는 여기에 복사해야합니다.

프로세스 힙 또는 ETS 테이블에서 가져온 것이 거의 다르지 않습니다 (즉, ETS에서 읽는 것이 종종 최적화되고 데이터를 가져 오거나 설정하는 것보다 다른 작업을 수행하지 않기 때문에 더 빠릅니다). 특히 원격 노드에서 데이터를 가져올 때. 멀티플 리더의 경우 ETS는 프로세스가 요청을 순차적으로 처리하기 때문에 가장 빠를 가능성이 큽니다.

그러나 차이점은 데이터가 로컬 노드에 캐시되어 있는지 여부입니다. 그것이 Mnesia, Riak 또는 CouchDB와 같은 자체 복제 데이터베이스 시스템이 등장하는 곳입니다. Mnesia는 실제로 ETS 테이블을 사용하여 구현됩니다.

Erlang의 최신 버전은 ETS의 개선 된 기능으로 여러 독자가 테이블과 동시에 기록하는 하나의 기록기에서 동시에 읽을 수 있습니다. 잠긴 요소는 하나의 데이터 포인트에 대해 많은 동시 읽기가 예상되는 경우에 쓰여지는 행입니다 (따라서 일반 프로세스보다 더 나은 동시 성능).

그러나 ETS 테이블과의 모든 상호 작용은 트랜잭션이 아닙니다. 즉, 그 동안 값이 변경되었을 수 있으므로 이전 읽기를 기반으로 값을 쓰는 것에 의존 할 수 없습니다. Mnesia는 거래를 사용하여 그것을 처리합니다. Moneis에서 여전히 dirty_* 기능을 사용하여 수행중인 작업을 알고있는 경우 거의 모든 작업에서 ETS 성능을 압박 할 수 있습니다.