거의 모든 조직은 사용자 데이터를 기록하고 불러와야 할 필요가 있습니다. 이러한 사용자 데이터는 정의된 설정, 기록 및 기본 설정이 있는 사용자 계정과 같이 영구적인 경우가 많습니다. 최근 활동만 있는 익명 세션의 경우처럼 일시적인 데이터인 경우도 마찬가지로 빈번하게 발생합니다. 두 경우 모두 조직은 데이터를 유지하고 쿼리하기 위해 사용자 프로필 저장소/세션 저장소가 필요합니다. 이러한 유형의 데이터는 대부분의 조직 내 많은 애플리케이션의 기반이 되므로 사용자 프로필 데이터베이스 설계는 성능과 가용성, 확장성을 갖춰야 합니다. 사용자 기본 설정을 데이터베이스에 저장하는 방법에 대한 이 게시물에서는 이러한 시스템을 살펴봅니다.
Couchbase의 강점을 살린 사용자 데이터 모델을 데이터베이스로 사용하는 프로필 저장 서비스(REST API)에 대해 살펴보겠습니다. 먼저 모든 데이터를 하나의 문서에 담는 것부터 시작하겠습니다. 그런 다음 이 문서를 별도의 문서로 정규화하는 방법과 이유, 그리고 변경의 근거를 살펴볼 것입니다. 이 모든 것은 사용자 프로필 데이터 모델에 가장 적합한 것이 무엇인지, 그리고 Couchbase Server의 기능을 어떻게 활용할 계획인지에 대한 관점입니다.
사용자 프로필 서비스 정의하기
예제 서비스와 그 매개변수를 정의하는 것부터 시작하겠습니다. 이 프로젝트를 위해 제가 직접 설정한 디자인 매개변수는 다음과 같습니다:
- 가상의 회사의 모든 고객 대면 마이크로 서비스에 대한 권한 있는 프로필 저장소이며 데이터에 대한 CRUD 작업을 지원하는 REST API를 노출해야 합니다.
- API는 설계 문서에 따라 기능이 유지되고 더 이상 사용되지 않는 버전으로 관리되어야 합니다.
- 가동 시간 목표는 99.999% 이상입니다.
- 사용자 프로필을 마지막 로그인 후 X년 동안 보관하도록 설정할 수 있어야 하며, 데이터베이스는 각 사용자의 객체에 대한 애플리케이션 설정 시간(TTL)과 함께 계정 데이터 삭제를 관리하는 것이 바람직합니다.'
- 이 서비스는 비교적 적당한 AWS 인스턴스 크기에서 초당 최소 50,000건의 인증과 10,000건의 기본 사용자 프로필 조회를 수행할 수 있어야 합니다.
REST API에서 노출되는 서비스 정의하기
데이터가 어떻게 사용될지 매핑하는 것부터 시작해야 합니다. 내 서비스가 노출할 인터페이스와 가장 많이 사용되는 인터페이스와 가장 적게 사용되는 인터페이스를 파악해야 합니다. 이렇게 하면 문서를 가장 잘 디자인하는 방법을 찾는 데 도움이 됩니다. Couchbase를 사용하면 데이터베이스가 데이터를 저장하는 방식이 아니라 애플리케이션이 데이터를 사용하는 방법, 시기, 빈도에 따라 문서 스키마를 설계할 수 있습니다.
다음은 이 서비스에 사용할 수 있는 몇 가지 예시입니다. 일일이 나열하여 시간을 낭비하지는 않겠지만 대략적인 내용은 이해하실 수 있을 것입니다.
- getUserProfile(userID) - 해당 사용자에 대한 DB의 모든 객체를 가져옵니다. 이 함수는 설정된 키 패턴 개체 이름의 배열(예: )을 읽은 다음 모든 사용자의 개체에 대해 일괄 가져오기 작업을 수행합니다.
- getSecurityQuestions(userID) - 사용자가 활성화되어 있는지 로그인 정보 문서를 확인하고, 활성화되어 있으면 사용자의 보안 질문 문서를 반환합니다. 사용자가 비활성화되어 있으면 오류를 반환합니다.
- setSecurityQuestions(userID) - 사용자의 보안 질문 문서를 작성합니다.
- authorizeUser(userID, passwordHash, IP) - 사용자의 인증 문서를 가져와서 isEnabled 함수를 호출하고 계정이 활성화된 경우 비밀번호가 일치하는지 확인합니다. 일치하면 IP와 마지막 로그인으로 문서를 업데이트합니다.
- isEnabled(userID) - 사용자의 로그인 정보 문서에서 계정이 시스템에서 활성화되어 있는지 여부를 확인합니다. 참 또는 거짓을 반환합니다.
애플리케이션 개발 및 샘플 코드에 대해 설명하는 뒷부분의 블로그 게시물에서 전체 방법 목록을 확인하세요.
초기 주 사용자 문서
다음은 서비스에 필요한 모든 데이터를 캡처하는 사용자 프로필 문서의 예시이며, 이는 완벽하게 유효한 방법이 될 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
키 : hernandez94 { "username" : "hernandez94", "firstName" : "Jennifer", "middleName" : "Maria", "성" : "Hernandez", "주소" : [ { "type" : "home", "addr1" : "1929 크리산토 애비뉴", "주소" : "Apt 123", "addr3" : "c/o J. 에르난데스", "city" : "마운틴 뷰", "state" : "CA", "country" : "USA", "pcode" : "94040" }, { "type" : "일", "addr1" : "2700W 엘 카미노 레알", "addr2" : "Suite #123", "city" : "마운틴 뷰", "state" : "CA", "country" : "USA", "pcode" : "94040" }, { "type" : "청구", "addr1" : "사서함 123456", "city" : "마운틴 뷰", "state" : "CA", "country" : "USA", "pcode" : "94041" } ], "이메일" : [ { "type" : "일", "addr" : "work@email.com" }, { "type" : "개인", "addr" : "personal@email.com", "primary" : true } ], "전화" : [ { "type" : "일", "num" : "+12345678900" }, { "type" : "모바일", "num" : "+12345678901" } ], "createdate" : "2016-08-01 15:03:40", "lastlogin": "2016-08-01 17:03:40", "pword": "앱-해시된-암호", "loc": "IP 또는 fqdn", "enabled" : true, "sec-questions" : [ { "question1" : "보안 질문 1은 여기로", "answer" : "보안 질문 1에 대한 답변은 여기에 있습니다" }, { "question2" : "보안 질문 2는 여기로", "answer" : "보안 질문 2에 대한 답변은 여기에 있습니다" }, { "question3" : "보안 질문 3은 여기로", "answer" : "보안 질문 3에 대한 답변은 여기에 있습니다" } ], "sec-roles" : [101, 301, 345], "문서 유형" : "user" } |
이 문서의 용량은 약 1.41KB이며 아직 모든 데이터가 완전히 채워지지 않았습니다. 따라서 이 문서는 사용자에 따라 더 커질 수 있습니다. 개발자가 있거나 문서나 표에 데이터를 추가하고 추가하고 추가하는 것을 좋아하는 개발자라면 애플리케이션/서비스가 발전함에 따라 문서가 많이 커질 수 있습니다. 애플리케이션에서 이 데이터를 언제 어떻게 사용할 것인지에 따라 이 문서를 최적화하는 방법을 살펴보겠습니다.
Couchbase의 데이터 액세스에 대한 간략한 설명
이 서비스의 주요 부분에서는 키를 통해 데이터에 액세스하고 데이터를 최대한 적게 쿼리할 수 있는 성능과 기능이 필요합니다. 리해싱 없이 데이터 액세스에 대한 저의 다른 블로그 게시물 를 너무 많이 사용하는 경우, Couchbase는 데이터에 접근할 수 있는 여러 가지 방법을 제공합니다. 원하는 개체의 ObjectID를 제공하면 애플리케이션이 데이터 서비스의 관리형 캐시에서 해당 개체를 매우 빠르게 읽고 쓸 수 있습니다.
카우치베이스의 N1QL 언어(~98%, ANSI 92 SQL 준수)를 사용하여 쿼리하려는 경우, 이는 데이터에 대한 질문이 있음을 의미하며 쿼리 서비스를 통해서도 쿼리를 수행할 수 있습니다. 쿼리는 더 많은 작업을 수행해야 하는 특성상 ObjectID로 데이터를 작업하는 것보다 성능이 떨어집니다. 질문(쿼리)이 있는 것과 이미 답변(ObjectID)을 알고 있는 것의 차이입니다. (제가 왜 이렇게 말하는지에 대한 자세한 내용은 다른 블로그 게시물 "기능 및 성능 요구 사항에 따라 Couchbase에서 데이터 액세스가 결정되는 방법“).
이 사용자 프로필 데이터베이스 스키마 설계에서는 필요할 때 두 가지 방법으로 개체에 효율적으로 액세스할 수 있도록 할 것입니다. 애플리케이션의 '핫 경로'는 가능한 한 ObjectID로 액세스하되, 필요한 경우 쿼리할 것입니다. 이 문서에서 위에 명시된 요구 사항을 충족해야 합니다.
주 사용자 문서 최적화
이 서비스를 위한 사용자 데이터 모델을 설계할 때 Couchbase의 확장, 성능 및 메모리 관리 방식에 다소 독특한 몇 가지 옵션을 사용할 수 있습니다. 모든 개체는 데이터 서비스의 관리형 캐시에 보관할 수 있으므로, 자주 필요한 데이터는 관리형 캐시에, 자주 사용하지 않는 데이터는 디스크에 보관할 수 있도록 서비스에서 사용하는 문서 데이터 모델과 키 패턴을 충분히 유연하게 만들 수 있기를 원합니다. 다른 NoSQL 문서 데이터베이스에서는 모든 데이터를 하나의 문서에 넣은 다음 해당 데이터를 쿼리해야 할 수도 있습니다. N1QL을 사용한 쿼리도 Couchbase에서 사용할 수 있으며, 저희는 이를 특정 목적으로 사용할 것입니다. 다시 말하지만, 유연한 데이터 모델과 내장된 관리형 캐시를 갖춘 Couchbase의 아키텍처는 이 기능을 활용할 위치 및 방법을 선택할 수 있는 기능을 제공합니다.
저는 키 패턴과 정규화된 데이터 모델을 사용할 것입니다. 이렇게 하면 필요할 때, 필요한 방식으로, 필요한 정확한 데이터만 읽고 쓸 수 있지만, N1QL로 데이터를 쿼리해야 할 때도 그렇게 할 수 있습니다. 이러한 디자인 패턴 중 일부는 이상하게 보일 수 있지만, 이러한 방식으로 초당 수만 또는 수십만 개의 작업, 또는 그 이상의 작업을 수행하도록 Couchbase를 쉽게 실행하고 확장할 수 있습니다. 다음 블로그에서는 분석 등을 수행하기 위해 데이터를 쿼리하는 방법에 대해 살펴보겠습니다.
다시 말하지만, 저는 애플리케이션이 필요한 데이터만 필요할 때 정확히 가져오고 쿼리하지 않고 키로 데이터를 읽는 것을 중심으로 문서를 설계하고 싶습니다. 인덱스, 뷰, 조인 등이 필요 없습니다. 이것이 바로 Couchbase를 통해 최고의 성능과 확장성을 얻을 수 있는 방법입니다.
로그인 정보 문서
몇 가지 이유로 사용자의 로그인 정보를 자체 문서로 분리했으며, 나중에 다른 문서에도 이와 같은 철학을 적용할 것입니다.
- 로그인 정보는 사용자가 애플리케이션에서 많이 인증하기 때문에 꽤 자주 필요하며, 서비스에서 이 데이터가 필요할 때 나머지 사용자 정보는 대부분 필요하지 않습니다. 예, Couchbase에는 하위 문서 편집 기능이 있지만 대부분의 NoSQL 데이터베이스와 마찬가지로 백엔드에서는 여전히 클러스터 간 복제(XDCR) 등 전체 문서가 재조립되어 전송됩니다. 저는 가능한 한 이 문제를 피하고 싶습니다.
- 차라리 서비스가 메인 문서가 포함된 14만 1천 개 이상의 문서를 모두 가져오는 것보다 141바이트인 문서 하나만 DB에서 애플리케이션으로 가져오는 것이 낫습니다. 하위 문서를 편집하면 이 문제를 완화할 수 있지만 다음 두 가지 이유는 해결되지 않습니다.
- 성능을 위해 항상 전체 문서가 필요한 것은 아니지만 대용량 문서 대신 141바이트의 문서를 관리형 캐시에 보관하는 편이 낫습니다. 사용자가 10만 명이고 초당 1000건의 작업만 수행하는 경우에는 전체 문서를 캐시에 보관하는 것이 크게 문제가 되지 않을 수 있지만, 사용자가 수백만 명이고 초당 10만 건은 아니더라도 수십만 건의 작업을 수행해야 하고 성능을 유지해야 하는 경우에는 문제가 커집니다. 성능과 금전적 리소스, 즉 RAM 모두에서 말이죠.
- 이렇게 하면 내 서비스의 일반 방문자의 경우 문서가 항상 관리되는 캐시에 있어야 최상의 성능을 얻을 수 있습니다.
또한 이 문서를 현재 날짜를 마지막 로그인 값으로 업데이트하고 사용자가 로그인에 성공할 때마다 로그인한 IP를 업데이트하고 싶습니다. 이것은 Couchbase에서 자동으로 추적하지는 않지만 비즈니스 분석 목적과 오랫동안 로그인하지 않은 사용자를 삭제하기 위해 필요합니다. 이 경우에는 아주 작은 문서만 업데이트하고 있습니다.
사용자를 인증하는 일상적인 작업에는 중요하지 않으므로 X년 동안 시스템에 로그인하지 않은 사용자를 삭제해야 한다는 요구 사항에 대해서는 다른 블로그 게시물에서 다룰 예정입니다.
또한 문서에는 사용자가 로그인할 수 있는지 여부를 확인하기 위해 서비스에서 사용할 수 있는 "enabled"라는 엔티티가 있습니다.
1 2 3 4 5 6 7 8 9 10 |
키 : 로그인-정보::hernandez94 { "lastlogin": "2016-08-01 15:03:40", "pword": "앱-해시된-암호", "loc": "IP 또는 fqdn", "enabled" : true, "문서 유형" : "로그인 정보", "username" : "hernandez94" } |
여기서 중요한 부분은 문서의 키입니다. 이러한 종류의 키 패턴은 나중에 보게 되겠지만 제 애플리케이션에서 일관된 패턴입니다. 애플리케이션에서 이를 고유한 사용자 이름과 쉽게 연결할 수 있습니다. 이 키가 중요한 이유는 Couchbase에서 이 문서를 쿼리할 필요가 없고, 키를 가지고 있기 때문입니다. 키를 안다는 것은 "내가 찾고 있는 이 데이터가 어디에 있는가?"라는 질문에 대한 답을 이미 Couchbase SDK가 알고 있다는 것을 의미하지만, 데이터베이스에 쿼리하는 것은 DB에 그 질문을 하고 DB의 마력(그리고 그에 수반되는 모든 것)을 사용하여 답을 찾아서 데이터를 가져오는 것입니다. 따라서 키를 알고 데이터베이스에 해당 개체를 읽거나 쓰도록 지시하는 것은, 특히 관리되는 캐시에 이미 있는 경우, Couchbase를 사용하면 매우 빠릅니다. 개체가 디스크에 있고 관리되는 캐시에 있지 않더라도 관리되는 캐시에 배치되어 후속 쿼리에 사용할 준비가 되면 속도가 빨라집니다. 캐시 관리는 백그라운드에서 이루어지므로 애플리케이션이 알 필요가 없습니다.
또한 Couchbase가 이를 지원하므로 JSON 문서의 "enabled" 엔티티를 자체 키/값 쌍 객체로 분리할 생각도 하고 있었습니다. 시스템에서 사용자가 활성화되어 있는지 여부를 알아야 하는 곳이 꽤 많을 것 같다는 생각이 들었기 때문입니다. 가능하지만, 이미 데이터를 많이 정규화하기 시작했고 어딘가에서 멈춰야 하기 때문에 그렇게 하지 않기로 결정했습니다. 이것은 복잡성을 위해 그냥 두는 것이 합리적이라고 판단한 경우입니다.
이 새 문서에서 주목해야 할 또 다른 사항 중 하나는 문서 스키마에 문서 유형 및 사용자 이름 엔티티를 추가했다는 점입니다. 다른 모든 문서에서도 이러한 엔티티를 볼 수 있습니다. 문서 유형은 나중에 2차 인덱싱을 할 수 있기 때문입니다. 사용자 이름은 인덱싱을 위한 것이기도 하지만, 이러한 문서와 새로운 기본 문서 간에 N1QL로 조인을 수행할 수 있기 때문입니다. 이 시리즈의 후반부에서는 이것이 중요한 이유와 이를 어떻게 활용하는지에 대해 자세히 살펴보겠습니다.
요약하자면, 기본 사용자 문서에서 이 정보 덩어리를 더 작은 문서로 분리한 데에는 몇 가지 좋은 이유가 있습니다. 이 문서는 자주 필요하고, 효율적인 읽기/쓰기를 위해 작게 유지하며, 관리되는 캐시에 보관해야 대부분의 사용자가 사용할 수 있습니다. 무엇보다도 키로 개체를 가져올 수 있기 때문에 데이터베이스를 쿼리할 필요가 없어 조회 속도가 매우 빠릅니다. 또한 나중에 더 쉽게 쿼리할 수 있도록 JSON 문서에 값을 추가했습니다.
보안 질문 문서
자주 필요한 로그인 정보 문서와 달리 이 데이터는 매우 드물게 필요하기 때문에 보안 질문 문서를 만들었습니다. 서비스에서 이 정보가 필요할 때는 특별히 나머지 사용자 정보가 필요하지 않습니다. 따라서 이를 자체 객체로 분리하고 다시 애플리케이션에서 쉽게 연결할 수 있는 키를 추가하여 키별로 문서를 가져오는 것이 합리적이라고 생각했습니다. 또한 이를 배열에서 각 질문이 고유한 객체가 되도록 변환했습니다. 이제 질문1.question 또는 질문2.answer와 같은 하위 개체 표기법으로 원하는 질문을 참조할 수 있으며 앱 코드에서 1에서 3 사이의 숫자를 임의로 생성한 다음 해당 질문 하나에 대해서만 하위 문서 API 가져오기를 사용할 수 있습니다. 또한 애플리케이션의 작동 방식에 따라 세 가지 질문을 모두 표시하는 옵션도 있습니다. 저는 옵션이 있는 것을 좋아합니다.
1 2 3 4 5 6 7 8 9 |
키 : 초-질문::hernandez94 { "question1" : { "question" : "보안 질문 1은 여기로", "answer" : "보안 질문 1에 대한 답변은 여기에 있습니다" }, "question2" : { "question" : "보안 질문 2는 여기로", "answer" : "보안 질문 2에 대한 답변은 여기에 있습니다" }, "question3" : { "question" : "보안 질문 3은 여기로", "answer" : "보안 질문 3에 대한 답변은 여기에 있습니다" }, "문서 유형" : "sec-questions", "username" : "hernandez94" } |
또한 문서가 자주 사용되지 않기 때문에 이 문서가 관리되는 캐시에서 빠질 수 있지만 저는 상관하지 않습니다. 사용자가 자주 사용하지 않으므로 성능에 약간의 타격이 있어 디스크로 이동해야 하는 경우 사용자가 알아서 처리하세요! 사용자 계정에 대해 기억할 수 없기 때문에 이 모든 데이터를 RAM에 보관하는 데 비용을 지불하지 않습니다.
사용자의 보안 역할 문서
사용자에게 연결할 보안 역할 목록을 갖고 싶었습니다. 다른 많은 것들과 마찬가지로 이 정보가 필요할 때 사용자에 대한 다른 정보는 필요하지 않습니다. 아마도 이 매핑이 적용되는 보안 역할을 정의하는 다른 문서가 어딘가에 있을 것입니다.
1 2 3 4 5 6 7 |
키 : 사용자-초-역할::hernandez94 { "sec-roles" : [101, 301, 345], "문서 유형" : "사용자 역할", "username" : "hernandez94" } |
보안 역할 문서
이러한 매핑을 위한 보안 역할을 정의하는 또 다른 문서 세트를 준비할 것입니다.
1 2 3 4 5 6 7 |
키 : 초-역할::101 { "name" : "관리자", "descr" : "서비스 관리자", "문서 유형" : "sec-role" } |
하지만 나중에 문제가 될 수 있는 흥미로운 문제입니다. 이 문서는 꽤 자주 읽힐 수 있기 때문에 애플리케이션이 얼마나 자주 사용하느냐에 따라 핫스팟이 생길 수도 있습니다. 한 고객은 애플리케이션 구성을 하나의 문서에 보관했는데 초당 10,000회 이상 읽는 것을 본 적이 있습니다. Couchbase의 단일 노드로는 이를 쉽게 처리할 수 있지만, 다른 모든 트래픽과 함께 처리해야 했습니다. 따라서 이 문서가 있는 클러스터의 한 노드에 과부하가 걸렸습니다. 이것은 여기서 문제가 되지는 않지만 지켜봐야 할 사항입니다. 나중에 이 문제를 해결하는 방법에 대한 후속 포스팅을 올릴 예정이지만 100번 중 99번은 문제가 되지 않을 것입니다. 카우치베이스에서 핫스팟을 본 것은 딱 한 번뿐이었고, 그 원인은 앱 디자인 문제였습니다.
이메일, 주소, 전화 문서
애플리케이션에서 데이터를 사용하는 방식에 따라 이메일, 전화 및/또는 주소 배열을 원본 문서에서 분리할 수 있습니다. 이 서비스의 일부로 노출되는 getEmail() 또는 getAddress() 메서드가 있을 수 있습니다. getMail() 메서드는 고유한 사용자 이름을 입력으로 받아 문서의 키(email-addr::hernandez94)를 쉽게 구성할 수 있습니다. 모든 데이터베이스의 정규화와 마찬가지로 너무 멀리 갈 수 있습니다. 따라서 확실한 이유가 있는 경우에만 조심해서 사용하세요.
1 2 3 4 5 6 7 8 |
키 : 전화::모바일::hernandez94 { "문서 유형" : "전화", "num" : "+12345678900", "type" : "모바일", "id" : "hernandez94" } |
아래와 같이 사용자가 가지고 있는 각 전화번호에 대해 문서를 작성하면 KV 액세스 및 N1QL 액세스 모두에 대한 옵션이 제공됩니다. 아래 쿼리는 이 사용자의 모든 전화번호와 그 유형(예: 모바일, 직장 등)을 가져옵니다.
1 |
선택 숫자, 유형 FROM 사용자 프로필 어디 id = "hernandez94" AND doc-유형 = "전화"; |
위 문서의 키도 마찬가지로 쉽게 구문 분석하여 KV를 통해 가져올 수 있습니다. 이렇게 하면 옵션이 제공됩니다.
새로운 메인 문서
이제 메인 문서가 완성되었습니다. 애플리케이션 사용자 패턴에 따라 주소와 전화번호 등을 분리할 수도 있지만, 예를 들어 여기에 남겨둔 모든 데이터는 자주 필요하지 않거나 필요할 때 동시에 필요한 데이터이기 때문에 그대로 두기로 했습니다. 더 정규화할 수 있나요? 예, 예를 들어 생성된 데이터를 기록하고 싶기 때문에 키 값 객체로 분리할 수 있지만, 거의 필요하지 않을 것이지만 현재로서는 이 방법으로 필요한 곳에 도달할 수 있습니다. 너무 미치고 싶지 않아요. 또한 문서가 많을수록 메타 데이터도 많아지니까요.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
키 : hernandez94 { "firstName" : "Jennifer", "middleName" : "Maria", "성" : "Hernandez", "주소" : [ { "type" : "home", "addr1" : "1929 크리산토 애비뉴", "주소" : "Apt 123", "addr3" : "c/o J. 에르난데스", "city" : "마운틴 뷰", "state" : "CA", "country" : "USA", "pcode" : "94040" }, { "type" : "일", "addr1" : "2700W 엘 카미노 레알", "addr2" : "Suite #123", "city" : "마운틴 뷰", "state" : "CA", "country" : "USA", "pcode" : "94040" }, { "type" : "청구", "addr1" : "사서함 123456", "city" : "마운틴 뷰", "state" : "CA", "country" : "USA", "pcode" : "94041" } ], "전화" : [ { "type" : "일", "num" : "+12345678900" }, { "type" : "모바일", "num" : "+12345678901" } ], "createdate" : "2016-08-01 15:03:40", "문서 유형" : "user" } |
샘플 Java 코드
다음은 사용자와 관련된 모든 문서를 가져오기 위한 대량 가져오기 작업의 Java 코드 예제입니다:
이를 통해 이 사용자와 관련된 모든 문서를 매우 쉽고 빠르게 가져올 수 있습니다. 마치 관계형 데이터베이스에서 서로 다른 데이터를 서로 다른 테이블에 넣은 다음 조인을 수행하여 모든 정보를 가져오는 것과 비슷합니다. 이 방법은 그보다 훨씬 빠릅니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
클러스터 클러스터 = 카우치베이스클러스터.create(); 버킷 버킷 = 클러스터.오픈버킷(); 목록 찾은 문서 = 관찰 가능 .그냥( userID, "초-질문::" + userID, "로그인 정보::" + userID, "user-sec-roles::" + userID) .플랫맵(new Func1<문자열, 관찰 가능>() { @오버라이드 public 관찰 가능 통화(문자열 id) { 반환 버킷.비동기().get(id); } }) .toList() .차단() .단일(); |
이 호출을 마쳤을 때 모든 문서가 있는지 확인하고 노드가 다운될 경우를 대비하여 누락된 문서에 대한 복제본 읽기를 수행하지 않는다면 코드를 수정하는 것이 어떨지 생각해 볼 수 있지만, 아이디어를 얻으실 수 있습니다.
대량 가져오기 방법에 대한 자세한 내용은 각 Couchbase SDK 설명서를 참조하세요.
요약
카우치베이스는 다른 문서 데이터베이스, 특히 관계형 데이터베이스와 달리 데이터를 모델링하는 다른 방법을 제공합니다. 일부 데이터를 여러 문서로 분리하되 키와 문서의 정보로 연관시켜 필요할 때 애플리케이션에 필요한 정확한 데이터를 얻을 수 있습니다. 자주 사용하는 데이터는 관리되는 캐시에 정확히 원하는 데이터를 최신 상태로 유지하지만, 사용자의 모든 문서가 필요한 경우 매우 빠르게 모든 문서를 대량으로 작업할 수 있습니다. 마지막으로 중요한 부분은 여기서 사용되는 키 패턴입니다. 다시 말하지만, 키로 개체에 액세스하는 것은 이미 답을 알고 있는 것과 다른 데이터베이스에서처럼 질문을 해야 하는 것의 차이입니다.
성능과 주요 패턴에 대한 이러한 모든 이야기는 실제로 데이터를 쿼리하고자 할 때를 무시합니다. "집 주소 우편번호가 98038인 사용자가 몇 명인가?"와 같은 질문이 있을 때를 예로 들 수 있습니다. 하지만 앞서 말씀드렸듯이 이 질문은 이 시리즈의 다른 블로그 게시물에서 다루도록 하겠습니다.
아주 잘 작성된 Kirk....이 시리즈의 파트 2를 간절히 기다리고 있습니다.
안녕하세요 커크, 멋진 글입니다. 저는 이제 막 NoSQL에 입문하여 Couchbase를 사용하기 시작했는데, 이 글은 훌륭한 학습 자료입니다.
기본적으로 문자열 키를 문서 간 조인으로 사용하는 방식이 마음에 듭니다. 좀 더 복잡한 시나리오에서 어떻게 해야 할지 고민 중입니다: 사용자가 트위터의 트윗과 관련된 추가 데이터(예: "이 트윗을 즐겨찾기로 저장"과 같은)를 저장할 수 있는 앱을 만들고 있다고 가정해 봅시다. 한 명의 사용자가 시간이 지남에 따라 수천 개의 즐겨찾기를 쉽게 쌓을 수 있습니다. 기본적으로 이것은 사용자와 트윗 간의 다대다 관계입니다. 이 작은 문서의 핵심은 다음과 같습니다: _
제 시나리오에서 이러한 모든 관계는 관계를 생성한 사용자에게만 엄격하게 비공개로 유지됩니다. 그리고 이 모든 관계는 Couchbase Lite를 통해 사용자의 장치에 복제되어야 합니다. 이러한 이유로 해당 사용자를 위해 단일 문서에 모두 저장하는 것이 더 나을까요, 아니면 시간, 트위터 스트림 등을 기준으로 분할된 문서에 저장하는 것이 더 나을까요?
고마워요!
두 가지 방법 모두 장단점이 있기 때문에 어려운 문제입니다. 하나의 문서에 모두 저장하면 사용자가 어느 시점에서 20MB 문서 제한을 초과하게 되거나 트윗 하나를 추가하기 위해 큰 JSON 문서를 드래그해야 하는 상황이 발생할 수 있습니다. 반대로 모든 트윗이 그 자체로 하나의 문서에 담겨 있다면, 수십억 개의 개체가 있고 데이터 개체당 최대 54바이트의 메타데이터를 저장하는 Couchbase에 많은 양의 메타데이터를 저장해야 하는 상황이 발생할 수 있습니다. 이 역시 삭제할 수 있지만 문서가 존재하는지 확인하기 위해 성능에 타격을 입게 됩니다.
어쨌든 세 가지 가능성을 살펴볼 것을 권장합니다.
1) 각 트윗을 객체로 저장하는 것이 효과가 있는지 확인하되, 다른 객체 모델링 블로그 게시물에서 설명하는 것이 핵심이 될 것입니다. http://bit.ly/1Hx3a74
2) 제가 사용해 본 또 다른 옵션은 각 트윗을 별도의 문서에 저장한 다음 사용자별로 수동으로 색인 문서를 만드는 것입니다. 따라서 해당 사용자의 즐겨찾기를 가져오려면 해당 사용자의 '색인'이 있는 문서를 가져오고 그 문서에는 해당 사용자가 즐겨찾는 트윗의 개체 ID 목록이 있습니다. 모두 가져와야 하는 경우 이제 가져올 개체 목록이 있으므로 Couchbase SDK의 대량 작업을 사용하여 전체 또는 필요한 부분만 가져올 수 있습니다. 이해가 되시나요?
3) 사용 사례와 필요한 성능 프로필에 따라 1과 2를 혼합하여 사용합니다.
좋은 기사입니다. 정보를 제공해 주셔서 감사합니다. 작성할 수 있는 "이메일 신청서 작성 방법" 공란을 어디서 찾을 수 있는지 아는 사람이 있나요?
안녕 지니, 나는
이 링크에서 \"이메일 신청서\"를 보낼 수 있었습니다.
http://goo.gl/yoGwr2. 또한 다운로드, 편집, 인쇄, 저장, 서명, 이메일 또는 팩스 전송도 가능했습니다.
누구에게 이메일을 보내는 방법은 무엇인가요?
좋은 기사였습니다, 감사합니다! 2부를 기다리고 있습니다.
좋은 기사입니다.
사용자 프로필 저장소의 데이터 모델링은 카우치베이스 서버만 사용하는 것을 고려하고 있는데, 카우치베이스 서버와 카우치베이스 모바일을 사용할 때 데이터 모델링에 대한 조언이 있으면 유용할 것 같습니다.
예를 들어 CouchBase Mobile을 사용할 때, SG 라우팅/ACL의 제약, 맵/축소 등을 통한 CouchBaseLite의 쿼리 제약 등을 고려해야 합니다.
카우치베이스 모바일은 제 전문 분야가 아니기 때문에 이 주제를 제대로 다룰 수 있을지 의문입니다. 그래도 도움을 줄 수 있는 분들에게 이 내용을 전달하고 글을 작성하겠습니다. 다른 옵션은 아직 사용하지 않았다면 Couchbase 포럼을 사용하여 이에 대해 문의하는 것입니다.
여기에서 시작하실 수도 있으며, 앞으로 몇 주 안에 더 많은 Couchbase Mobile 교육을 공개할 예정입니다. http://developer.couchbase.com…
훌륭한 기사 커크. 매우 상세한 정보입니다. 이 글의 2부에 대한 날짜를 염두에 두고 있나요?
고마워요!
[...] 애플리케이션에서 표준화된 개체 ID 패턴을 사용하는 방법에 대한 예시는 이 블로그 게시물과 제가 작성한 이 블로그 게시물을 참조하세요. 블로그의 특정 사용 사례가 [...]에 적용되지 않는 경우에도 [...
이 문제를 얼마나 아름답게 해결했는지 공유해 주셔서 감사합니다.
포장 및 인쇄 공급업체