2011-02-04 8 views
0

한 번에 많은 양의 레코드를 보유 할 수있는 데이터 캐싱 시스템을 설계하고 있으며 사용할 컨테이너와 사용 방법을 알아야합니다. 응용 프로그램에는 사용자를위한 매우 큰 DB 레코드가 있습니다. 시스템에 로그인 할 때 사용자 이름 및 몇 가지 중요한 속성과 같은 일부 데이터를 기록하고 캐시하려고합니다. 그들은 시스템과 상호 작용하면서 해당 속성을 업데이트하고 액세스합니다. 몇몇 속성은 매우 휘발성이며 많은 트랜잭션이있는 DB에서 "치는"현상을 피하기 위해이 작업을 수행하고 있습니다. 또한 필자는 정렬이나 기타 용도로 데이터베이스를 사용할 필요가 거의 없다 - 필자는 영광스러운 바이너리 저장 파일 (이 때문에 메모리에 레코드를 캐시하는 것이 행복하다)과 같이 이것을 사용하고있다. 나를 위해 더 중요한 목표는 엄청난 수의 사용자로 확장 할 수 있다는 것입니다.MySQL DB에서 캐싱 데이터 - 기술 및 적절한 STL 컨테이너?

사용자가 로그 아웃 할 때 서버가 종료되거나 이 라운드 로빈 방식으로 (주기적으로)으로 주기적으로 데이터를 DB에 기록하려고합니다.

서버는 자체 유지 :

UserData를 유지하는 DB를에서 사용자 이름 (문자열) 및 기타 속성 같은 것들뿐만 아니라, 네트워크 핸들 같은 다른 임시 데이터와
vector <UserData *> loggedInUsers; 

.

이 벡터에서 특정 사용자를 찾으려면 가장 빠른 방법이 있습니까?이 작업을 수행하는 데 사용할 수있는 다른 컨테이너가 있습니까? 지금 내가하는 일은 iterator를 만들고, loggedInUsers.begin()에서 시작하여 .end()에 반복하여 * iter-> username == "foo"를 확인하고 발견되면 반환하는 것입니다. 사용자 이름이 벡터 끝에 있거나 벡터에 5000 명의 사용자가있는 경우 이는 상당한 지연입니다.

내 두 번째 질문은이 데이터를 DB에 다시 쓰도록 라운드 로빈 방식으로 예약 할 수 있습니까? DB에 몇 개의 레코드를 쓸 준비가 될 때마다 함수를 호출 할 수 있습니다. 하지만 벡터에 반복자를 넣을 수는 없으므로 무효화됩니다. 내가하고 싶은 것은 큐의 헤드에 액세스 할 수있는 순환 큐를 DB에 유지 한 다음 큐의 끝으로 회전시키는 것입니다. 오버 헤드가 많은 것처럼 보입니다. 어떤 형식으로이 작업을 더 잘 수행 할 수 있습니까?

제 3의 질문은 MySQL 서버와 libmysqlclient connector/C ..를 사용하고 있습니다.이 문제를 "무료"로 해결할 수있는 캐싱이 내장되어 있습니까? 아니면 전혀 다른 기술이 있습니까? 제안에 대한 답변을드립니다.

답변

1

A1. 당신은지도를 가지고있는 것이 더 낫습니다. 이것은 당신 조회를하는 나무입니다. 지도와 (올바른 컴파일러가 있다고 가정) 또는 hash_map (동일한 작업을 수행하지만 검색 메커니즘이 다릅니다)으로 테스트하십시오.데이터 저장 작업 부하의 유형에 따라 성능 특성이 다릅니다.

A2. 목록이 아마도 당신에게 더 나을 것입니다. 앞쪽으로 밀고 끝내십시오. (deque도 사용할 수 있지만 지우는 경우 iterator를 유지할 수 없습니다. 목록에서 지울 수 있습니다). push_back 및 pop_front (또는 그 반대)를 사용하면 캐시 된 데이터의 롤링 대기열을 유지할 수 있습니다.

A3. 당신은 SQLite를 시도 할 수 있습니다. SQLite는 단순한 애플리케이션 레벨 db 스토리지 요구를 위해 설계된 미니 데이터베이스입니다. 그것은 entirely in-memory 너무 일할 수 있습니다.

+0

A1 : 감사합니다. A2 : 끌어 오기/밀기의 성능은 어떻습니까? 각 작업에서 내가 새 요소를 버리고 추가한다고 가정 할 것입니까? 단지 '회전'하도록 만들어진 데이터 구조체가 있습니까? A3 : 여러 앱이 DB에 충돌 할 수 있습니다. 더 큰 질문을 따르십시오 : A1과 A2 나는이 모든 데이터를지도에 담아서 DB를 통해 업데이트를 지속하기 위해 회전 할 수 있도록 결합해야합니다. 어떻게 할 수 있습니까? – Nektarios

+0

A3에 대해 유감스럽게 생각합니다. SQLite를 메모리 내에서 데이터 구조로 사용할 것을 제안합니다. 그것은 실제로 좋을 것입니다. – Nektarios

1

시스템에서 수행하는 작업이나 액세스 방식에 대해서는 말하지 않지만 이러한 기술은 잘 확장되지 않습니다. 결국 메모리가 부족해지기 때문에 정보가 데이터베이스만큼 효율적이지는 않음), 데이터가 서로 올바르게 공유 될 수 있는지 확인하지 않는 한, 동시 사용자를 올바르게 처리 할 수 ​​없습니다.

그렇다면 사용자 이름을 키로 사용하여지도 (http://www.cplusplus.com/reference/stl/map/)를 사용하는 것이 더 나을 것입니다.

데이터베이스에 다시 쓰는 관점에서 데이터베이스에 쓸 때마다 지울 수있는 별도의 구조 (큐)를 저장하지 않으시겠습니까? 포인터를 저장하는 한 훨씬 많은 메모리를 사용하지 않습니다. 어느 날 나를 데 려 온다 .. 포인터를 사용하는 것보다는 소유권에 대해 걱정하지 않고 스마트 포인터 (예 : boost's shared_ptr)를 사용하면된다.

+0

감사합니다. 좋은 조언이 있습니다. 내 애플리케이션을 더 잘 정의했을 수 있습니다. 내 데이터가 작아서 절대 최대 64 바이트라고 할 수 있습니다. 즉, 1GB RAM에서 1600 만 명의 사용자가 메모리에 있어야하므로 아무 문제가 없습니다 (네트워크 소켓 설명자가 부족할 것입니다). 나는 포인터를 들고 당신이 shared_ptr을 도와주는 것을 보았습니다. – Nektarios