라벨이 MongoDB인 게시물 표시

(MongoDB) Sharding 및 Replication 구성하기 ver3.4

이미지
먼저 1. mongod서버 2. config서버 3. mongos가 필요하다 * mongod는 몽고 데이터를 저장하는 곳 * mongos는 request의 라우터 역할을 한다. * config는 데이터를 저장하지 않고 mongos로 부터 request가 들어왔을 때, 해당 데이터가 어느 샤드에 있는지 알려준다. * mongos는 config서버의 데이터를 캐쉬한다. 1. mongod 구성 * SHARD1 > --shardsvr --port 27017 --dbpath /data/db --replSet reply_replica (Secondary) > --shardsvr --port 27012 --dbpath /data/shard1 --replSet reply_replica  (Primary) > --shardsvr --port 27013 --dbpath /data/shard2 --replSet reply_replica (Secondary) *SHARD2 --shardsvr --port 28017 --dbpath /data/db1 --replSet shard2_replset (Primary) --shardsvr --port 28117 --dbpath /data/db1_replica1 --replSet shard2_replset (Secondary) 2. config 서버 구성 > mongod --configsvr --port 27010 이제 샤드를 등록해야 하는데 config서버에 해당 샤드 들을 등록해야하는데 ver3.4부터는 샤드의 replica만 등록 가능하다 그러므로 replica를 만들어야한다. 일단 Primary에 해당하는 27017포트에 해당하는 녀석에 접속한다 > mongo localhost:27017 그 후 rs.initiate()로 replicaSet을 구성한다. 해당 27017포트는 Primary가 된다 그 후 rs...

(MongoDB) ConfigServer 3.4 특징

config servers: Config servers store metadata and configuration settings for the cluster. As of MongoDB 3.4, config servers must be deployed as a replica set (CSRS).

(MongoDB) Mongos 프로세스

* Mongos 프로세스의 주요 특징 빅데이터를 샤드 서버로 분배해 주는 프로세스 하나이상의 프로세스가 활성화 된다. Application Server에서 실행이 가능하다 CONFIG 서버로 부터 Meta-Data를 캐시한다.

(MongoDB) 메모리영역 체크 명령어

1. db.serverStatus().mem {  "bits" : 64 //시스템 처리사양(64비트)  "resident" : 42 //Working Set 저장을 위한 메모리크기  "virtual" : 275, //Virtual 메모리 현재크기  "mapped" : 80m //Mapped File 현재크기 } 2. db.serverStatus().extra_info {  "page_faults" : 11722, //현재 메모리 페이지 폴트 수   "ramMB" : 3885 , //현재 시스템 메모리 크기수 }

(MongoDB) WiredTiger 엔진 특징

1. Document-Level Lock 제공으로 다수의 사용자가 트랜잭션 위주의 데이터를 빠르게 처리할 수 있도록 동시성을 제공합니다. 2. 인메모리 구조의 개선으로 몽고 디비 서버의 빠른 처리 성능이 개선되었습니다. 3. Memory Mapping 저장엔진은 단일 CPU 중심의 프로세싱 구조라면 wiredTiger 저장엔진은 Multi-Core 를 활용할 수 있는 시스템 구조이다. 다중쓰레드를 통해 집중화를 최소화 하였으며 동시성을 향상 시켰습니다. 4. CheckSums기능을 통해 시스템 장애 또는 저장 장치 장애로 부터 발생하는 데이터 유실을 최소화 할 수 있습니다. File system의 훼손 상태를 분석할수 있는 기능이 추가되었습니다. 5. 압축(Compression)기능을 통해 저장공간의 최소화가 가능합니다. 기본적으로 Snappy Compression 기능을 제공 

(MongoDB) 읽기 격리성, 일관성, 그리고 최신성

1. 트랜잭션이 보장해야 하는 ACID 원자성(Atomicity) : 한 트랜잭션 내에서 실행한 작업들은 모두 하나의 작업으로 간주한다. 모두 성공 또는 모두 실패되어야한다. 일관성(Consistency) : 모든 트랜잭션은 일관성있는 데이터베이스 상태를 유지해야 한다. DB에서 정한 무결성 조건을 항상 만족 격리성(Isolation) : 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않아야 한다. 지속성 (Durability) : 트랜잭션을 성공적으로 마치면 그 결과가 항상 저장되어야 한다. 격리성에 대한 이슈가 존재한다. 격리성을 완전히 보장하기 위해 모든 트랜잭션을 순차적으로 실행한다면 동시성 처리 이슈가 발생한다. 반대로 동시성을 높이기 위해 여러 트랜잭션을 병렬처리하게 되면 데이터의 무결성이 깨질 수 있다. * Serializable Isolation Level 이란?  - SELECT 수행시 READ LOCK ,즉  sharded lock을 사용 - 트랜잭션이 완료될 때까지 SELECT 문장이 사용하는 모든 데이터에 sharded lock이 걸리므로 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정 및 입력이 불가능하다. * 몽고DB의 격리성 Read Uncommitted 몽고디비에서는 클라이언트가 끝나지 않는 쓰기 작업(durable) 에 접근할 수 있다. Read Uncommitted는 디폴트 설정으로 mongod인스턴스와 레플리카셋 샤드 클러스터에 적용할 수 있다. Read Uncommitted And Single Document Atomicity single 쓰기 수행작업이 단건이 아닌 여러개의 documents를 수정할 때,  각각의 document에는 원자성(atomic)이 보장된다. 그러나 그 수행작업 전체에는 원자성이 보장되지 않고, 다른 수행작업이 간섭할 수 있다. 그래서 다음과 같은 특징을 ...

(MongoDB) Partial Index

Partial Index를 만들기 위해서는 db.collection.createIndex()메소드를 사용한 후, partialFilterExpression을 옵션으로 사용할 수 있다. equality expressions (i.e. field: value)또는 $eq $exists: true expression $gt, $gte, $lt, $lte expressions $type expressions $and operator at the top-level only 예) db.restaurants.createIndex(    { cuisine: 1, name: 1 },    { partialFilterExpression: { rating: { $gt: 5 } } } ) 다음 인덱스는 rating이 5보다 클 경우만 인덱스가 생성된다. db.restaurants.find( { cuisine: "Italian", rating: { $gte: 8 } } ) 위 쿼리는 8 이상인것만 조회를 시도하므로 생성된 인덱스를 사용할 것이다. 그러나 db.restaurants.find( { cuisine: "Italian", rating: { $lt: 8 } } ) 이 쿼리는 8미만인것을 조회하므로 인덱스 조건인 5보다 큰 경우에 위배되는 상황이 발생하므로 인덱스를 사용하지 않을것이다. db.restaurants.find( { cuisine: "Italian" } ) 그저 filter조건에만 해당하는 위 쿼리도 인덱스를 사용하지 못한다. 주의사항 :  _id필드는 partialIndex가 될 수 없다. Shard key indexes cannot be partial indexes.

(MongoDB) Compound Index 설계하기

세가지 케이스가 존재 1.   db.students.createIndex({student_id: 1, class_id: 1}) db.students.find({student_id:{$gt:500000}, class_id:54}) .sort({student_id:1}) .explain("executionStats") 위 인덱스를 태워 쿼리를 조회 할 떄와 db.students.createIndex({class_id:1, student_id:1}) 이 인덱스와 성능을 비교하면 참고로 class_id의 분류 갯수는 800 여개 아래 인덱스를 탈 때 더 좋은 성능을 보여준다. 즉, 먼저 필터역할을 하여 스캔해야할 document를 줄인다. 만약 db.students.find({student_id:{$gt:500000}, class_id:54}) .sort({final_grade:1}) .explain("executionStats") final_grade로 정렬할 필요가 있다면, 현재 인덱스로 쿼리를 타게되면 몽고디비 메모리 상에서 위 인덱스를 sort하게 되어 더 나쁜 현상을 보인다. 즉, db.students.createIndex({class_id:1, final_grade:1, student_id:1}) 이 인덱스로 해당 쿼리를 조회해주면 된다. 결과적으로 compoundedIndex는 Keys for equality filters should appear first. Keys used for sorting should appear before multi-value fields . Keys for multi-value filters should appear last. 다음과같이 디자인하는것이좋다.

(MongoDB) How MongoDB Selects an Index

How MongoDB Selects an Index Now let’s take a look at how MongoDB chooses an index to satisfy a query. Let’s imagine we have five indexes. When a query comes in, MongoDB looks at the query’s shape. The shape has to do with what fields are being searched on and additional information, such as whether or not there a sort. Based on that information, the system identifies a set of candidate indexes that it might be able to use in satisfying the query. Let’s assume we have a query come in, and three of our five indexes are identified as candidates for this query. MongoDB will then create three query plans, one each for these indexes. In three parallel threads, MongoDB will run the query such that each one will use a different index. The objective here is to see which one is able to return results the fastest. Visually, we can think of this as a race, something like in the graphic below. The idea here is that the first query plan to reach a goal state is the winner. But more important...

(MongoDB) 복합인덱스 사용시 중요한점

다음가 같은 예가 있다. 인덱스는 db.collection("users").ensureIndex({"age" : 1, "username" : 1}) db.collection("users").ensureIndex({"username" : 1, "age" : 1}) 두개가 있다. 다음 두 조건으로 검색한다고 하면, 1 . db.collections("users").find({"age" : {"$gte" : 21, "$lte" : 30}})  .sort({"usernmae" : 1})  .limit(1000) .hint({"age": 1, "username" : 1}) .explain() 2. db.collections("users").find({"age" : {"$gte" : 21, "$lte" : 30}})  .sort({"usernmae" : 1})  .limit(1000) .hint({"username": 1, "age" : 1}) .explain() - > 어느것이 더 성능이 좋을까? 2 번이 더 성능이 좋다? 인덱스는 앞의 키부터 타기 때문에 1번이 좋다고 생각 할 수 있지만, 인덱의 정렬순서는 왼쪽 최말단이 가장 작은 값이,  오른쪽 최말단 리프에 가장 큰 값이 들어가는 트리구조다 기본적으로 시간에 따라 탐색하기 때문이다. 즉, {"정렬키" : 1, "쿼리 검색 조건" : 1} 형태의 인덱스 조건이 애플리케이션에서 대체로 잘 동작한다. 따라서 오래된 데이터보다 최신의 데이터를 사용하는 경향이 있는 애플...

(MongoDB) Sharding split

* split이란? chunk를 split하여 두 개의 chunk 로 만드는것을 말한다. 일반적으로 mongos에서는 split기능이 automatically로 작동하지만, 관리자에 의하여 수동적으로 split 할 수가 있다. db.adminCommand({split : <database>.<collection>, <find | middle | bounds>}) 예) db.runCommand( { split : "example.User", middle : {location: 0 }})

(MongoDB) Sharding Balancer란?

* 몽고디비 Balancer란? 이 기능은 백그라운드 프로세스가 청크의 수와 각각의 샤드를 감시하는 기능이다. 만약 청크가 주어진 샤드에서 migration thresholds에 도달한다면, 밸런스는 자동으로 그 청크를 다른 샤드로 이동시킨다. 밸런서란, 각각의 청크들이 샤드 콜렉션에 고르게 분포되도록 만들어 주는 것이다. default는 밸런스 프로세스가 항상 enabled이다. * sh.setBalancerState(boolean) -> 이 메소드는 밸런스 기능을 enabled할것인지, disabled할 것인지 설정하는 것이다. 이 메소드를 실행 할 수 있는 곳은 mongos에서만 가능하다. 만약 mongod인스턴스에서 한다면 에러가 발생 할 것이다. 만약, 현재 밸런스 기능이 작동하는지 확인하고 싶다면, sh.isBalancerRunning()를 호출하던지 sh.getBalancerState()를 호출한다.

(MongoDB) Sharding (샤딩)

* 샤딩의 목적 1) 데이터의 분산 저장 하나의 서버에 빅 데이터를 저장, 관리하는것은 어렵다. 초당 발생하는 빅데이터를 디스크에 저장할때 발생하는 Write Scaling 문제는 애플리케이션의 성능 저하문제를 유발시키게 될 뿐 만 아니라 샤딩 시스템 전체의 성능 저하 현상을 유발 2) 빠른 성능 분산 처리는 여러 개의 프로세스가 여러 개의 CPU를 통해 동시 작업을 수생했을 떄 가장 이상적이라 볼 수 있다. 3) 데이터의 백업과 복구 전략의 일환 샤딩의 가장 대표적인 기능 중에 하나는 데이터의 분산 저장을 통한 시스템의 성능 향상이라고 볼 수 있다. 만약, 하나의 서버에 빅데이터를 저장, 관리 했을 때 서버의 장애 문제가 발생한다면 유실되어지는 데이터 양은 상상을 초월하게 될 것이고, 시스템을 복구하게 된다면 많은 시간과 비용이 요구 되어 질것이다. ========================================================== 1. 샤딩의 작동 방식 - 샤딩의 구성요소 샤드 클러스터는 샤드, mongos라우터, 설정서버로 구성된다. * 샤드 몽고디비 샤드클러스터는 데이터를 하나 혹은 그 이상의 샤드에 걸쳐서 분산저장한다. 각 샤드는 MongoDB의 복제셋으로 클러스터 전체 데이터의 일부분을 저장한다. *Mongos 라우터 각 샤드가 전체 데이터의 일부분만을 가지고 있다면, 그 일부가 어디있는지 알기 위한 인터페이스가 필요하다. mongos 프로세스는 모든 읽기와 쓰기 요청읋 해당 샤드에 보내는 라우터이다. 그러나 mongos는 지속성이 없는 경량 프로세스이다. 애플리케이션이 실행되는 서버에서 실행됨으로써 각 샤드에 연결되게 된다. *설정서버 mongos라우터가 지속성이 없기 때문에 샤드 클러스터의 상태를 어디선가는 유지하고 있어야 하는데, 그것이 설정 서버(config server)이다. 메타데이터를 지속적으로 유지한다. <컬렉션에 대한 샤딩...

(MongoDB) A single update on a sharded collection must contain an exact match on _id error

In sharding Mongodb cluster If you do CUD working, it is possible to show you next possible A single update on a sharded collection must contain an exact match on _id (and have the collection default collation) or contain the shard key (and have the simple collation). Update request This happend when I did updateFirst query in MongoDB. Beacuse shard cluster does not find where this document, the mongos can not find where it is. actuall UpdateFirst means that to update one document. If Mongos brodcast all shard cluster to update, it is to violate {multi: false} pharse. Therefor, to solve this error, we need to do one of three 1. to add shard key in query 2. to specify "_id" field which is unique key 3. to configure { multi : true }

(MongoDB) A single update on a sharded collection must contain an exact match on _id 에러 상황

샤딩이 된 mongoDb 서버 환경에서 CUD작업이 이루어지면 다음과같은 에러가 발생할 수 있다. A single update on a sharded collection must contain an exact match on _id (and have the collection default collation) or contain the shard key (and have the simple collation). Update request 위 상황은 해당 도큐먼트를 업데이트(updateFirst) 할 때 발생한 상황이다. 이러한 이유는 샤드 클러스터가 해당 도큐먼트가 위치하고 있는 샤드클러스터를 발견하지 못하고 있기 때문이다.   해당 쿼리문에 shard key를 포함하지 않고 있었습니다. 그러므로 해당 도큐먼트를 확인하기 위해서는 모든 샤드클러스터를 확인해야 하는데 mongos는 그 위치를 알아 낼 수 없습니다. 만약 mongos가 모든 샤드클러스터를 brodcast하여 업데이트를 하게 된다면 multi:false라는 구문에 위반되는 상황입니다. 그러므로 위와같은 에러를 방지하기 위해서는 1. shardKey를 추가하거나  2. unique key값인 _id필드를 명시하거나 3. multi : true롤 설정해야 합니다.

(MongoDB) How to use AbstractMongoDBListener (Example)

What is MongoListener? This is eventListener when MongoDB collections has been changed it can help developer do something ( after saving mongodb, elastisearch works next...etc) First of all,  i will show you methods in AbstractMongoDBListener If you want to read detail, you can find it springMongoDB Document. ================================================== void onAfterConvert(AfterConvertEvent<E> event) void onAfterDelete(AfterDeleteEvent<E> event) void onAfterLoad(AfterLoadEvent<E> event) void onAfterSave(AfterSaveEvent<E> event) void onApplicationEvent(MongoMappingEvent<E> event) void onBeforeConvert(AfterConvertEvent<E> event) void onSave(AfterSaveEvent<E> event) ===================================================================== example) I will show you how to use onSave method with overriding This example is  for Listener class when an event is occured from example class class ExampleListener ...

(MongoDB) AbstractMongoListener Usage example(몽고리스너 사용법)

몽고리스너란, MongoDB 컬렉션에 변화가 발생할 경우 이러한 이벤트에 따라 사용자가 정의한 행위를 실행하는것을 도와주는 이벤트 리스너이다. 먼저, AbstractMongoListener 의 메소드를 설명하겠습니다. void onAfterConvert(AfterConvertEvent<E> event) void onAfterDelete(AfterDeleteEvent<E> event) void onAfterLoad(AfterLoadEvent<E> event) void onAfterSave(AfterSaveEvent<E> event) void onApplicationEvent(MongoMappingEvent<E> event) void onBeforeConvert(AfterConvertEvent<E> event) void onSave(AfterSaveEvent<E> event) 예) Onsave메소드를 오버라이에서 사용하는 방법을 알아보자 이 예시는 Example클래스에 이벤트가 발생했을 때, 일어나는 리스너 클래스이다. Example 클래스에 save가 일어난 후 다음과 같이 특별ㅎ class ExampleListener extends AbstracMongoListener<Example> { @Override public void onAfterSave(AfterSaveEvent<Example> event) {   Example ex = event.getSource();  //이 아래부터 개발자가 원하는 처리를 할 수 있다. } 단, 주의 사항은 onAfterSave같은 경우는 MongoDB에 insert, insertList, save메소드가 발생했을 때만, 이 리스너 메소드가 호출된다. updateFirst, updateMulti, findAndModify가 ...

(MongoDB) MySql, MongoDB 둘다 적용하는 하이브리드형 개발 주의사항

두 디비를 적용하여 JPA @Transient를 적용할시 주의 사항이 있다. 도메인 객체 클래스에 특정 필드에 @Transient javax.persistence패키지용 어노테이션을 사용하면, 이건 MySql 디비에만 적용된다. 즉, MongoDB에는 위 어노테이션이 적용되지 않는다. 반면, org.springframwork.data.annotation용 Transient를 적용하면 MongoDB에 적용되지만, MySQL에 디비를 붙이는 서버가 올라가지 않는 문제가 있다. 만약 두 디비를 적용하고 한 클래스에서 @Transient어노테이션의 기능을 사용하고 싶다면 JPA용 javax.persistence 패키지의 @Transient를 사용하고, 몽고디비의 converter와 MongoDB Listener을 이용해 몽고디비 저장을 호출하기전 컨터버 기능을 작동해 Reflection을 이용해 위 두 어노테이션으 붙은 필드(변수를) 제거하여 위 기능을 사용하는 방법이 있다. 위 두 어노테이션이 적용되도록 하는 어노테이션을 따로 개발할 예정이다.

(MongoDB) Update

* Update는 인자값이 두개가 아니라 총 4개가 있다. 예) db.test.update( { 조건 } , { 변경값 }, true|false, true|false) 1번인자 : 조건 2번인자 : 변경조건 3번인자 : upsert(upsert란? 있으면 업데이트 없으면 insert하라는 것, 기본값은 false) 4번인자 : 멀티라인 조건여부(기본값 false) * 몽고디비 업데이트시 새로운 필드를 추가하는 경우는 $set을 사용하고, 기존에 있는 필드에 다른 값을 더 추가하고 싶은 경우 $push나 $addToSet를 사용한다. 단, $addToSet은 값을 추가할 때, 중복되지 않도록 확인한다.

(성능개선) MongoDB query (when choosing 11 list in each data for just one query)

* 몽고 디비 쿼리작업 db.getCollection('guestbookReply').aggregate([  {"$sort" : {regDt : 1}},  {"$match": {guestbookId : {"$in" :[ObjectId("58f6c9d49a72b291f14afe04"), ObjectId("58fde40e9a72b5cd0c88ae6e"),ObjectId("593fbb103b8baa7d5b6921c7")      ,ObjectId("593fbb663b8bc590ac3f4799")]}}  },  {"$group" : {   "_id":"$guestbookId",   "GuestBookReply":{"$push" : "$$ROOT"}},  },  {"$project" : {      "GuestBookReply" : {"$slice" : ["$GuestBookReply",10]}      }} ]); ====================================================== db.getCollection('guestbookReply').aggregate([ //{"$sort" : {regDt : 1}},  {"$match": {guestbookId : {"$in" :[ObjectId("58f6c9d49a72b291f14afe04"), ObjectId("58fde40e9a72b5cd0c88ae6e"),ObjectId("593fbb103b8baa7d5b6921c7") ...