'전체 글'에 해당되는 글 96건

Shading

mongoDB 2014. 4. 23. 16:28

mongoDB에서 샤딩을 해주기 위해서는 shard key를 정해주어야 한다.

샤딩을 하는 이유는 읽기와 쓰기를 분산시켜 디비의 부하를 줄이기 위함인 것처럼

이 목적을 가장 잘 달성할  수 있는 컬럼을 shard key로 잡아야 한다.

거의 대부분은 _id를 샤드키로 잡고 쓴다고 하고, mongodb도 기본적으로 _id에 맞추어 샤드를 테스트하고 최적화 했을 것이다.

샤딩 key로 데이터쓰기를 할때 range 방법과 hash방법이 있는데, range는 데이터가 얼마나 들어올지 fix된 상황에 적합할 것이고, 대부분의 경우는 hash방법이 좋지 않을까 생각한다.

그리고 샤드는 컬렉션 단위로 이루어지는데, 디비에 저장된 전체 데이터를 읽어서 처리해야 하는 데이터같은 경우는 샤드에 포함시키지 않아야 한다. 샤드된다면 각 샤드를 모두 뒤져서 가져와햐 하기 때문이다. 이때 샤드에 포함되지 않은 컬렉션은 따로 디비를 만들어 사용할 수도 있지만 그렇지 않은경우는 샤드들중 primary shard에 저장된다. 따라서 request에 따라서 primary shard에 부하가 집중될 수도 있으니 디자인을 잘 설계해야 할 것이다.

그리고 샤드들중 db하나가 lock이 걸리면 다른 샤드들은 정상동작하고 하나의 샤드만 lock이 걸린다. (collection이 1,2,3,4로 나눠졌을때 3번샤드의 collection때문에 락이 걸리면 그 collection이 속한 db가 락이 걸릴텐데 이때 3번샤드의 db만 락이 걸린다는 소리)  

블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,

물론 안써도 되게 만드는 방법이야 있겠지만 mysql을 쉽게 버릴수 없는 이유를 살펴보자.

mongoDB과 다르게 mysql의 장점은 트랜젝션이다.

트랜젝션은 atomic이 보장되고 중간에 실패하더라도 실질적인 영향을 미치지 않도록 할 수 있다. 하지만 mongodb같은 경우 각각의 쿼리들이 나눠있고 따로 불러야 하기 때문에 중간에 디비가 뻣거나 문제가 생길경우 대처하기가 어렵다.

그리고 atomic을 보장해야하는 상황을 예로들면 select하고 이 결과가 없다면 insert하는 하나의 트랜젝션은 중간에 다른 놈이 insert를 안했다는 보장을 받아야 한다. 하지만 nosql은 select와 insert가 나눠있기 때문에 select를 해왔을때는 없었지만 insert를 할때 없을거라는 보장을 할 수 없다. 

블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,

간단히 naver.com 홈페이지를 fetch해오는 로직이 있다고 하자.

그리고 post request를 날려 이로직이 끝난뒤에 response를 받고 싶다면?


잘못된 사용 예)

    def post(self):

        self.test("test")

        print "done"


    @gen.coroutine

    def test(self, msg):

        print msg

        httpClient = AsyncHTTPClient()

        res = yield httpClient.fetch("http://www.naver.com")

        print res

        print "done"

        raise gen.Return(res) 

이렇게 하면 result는 이렇다

test

done

[web:1728] 200 POST /test (::1) 2.23ms (connection 종료, response 보냄)

HTTPResponse(...)

self.test()함수를 기다리지 않고 바로 done하고 response를 날리고 나중에 res가 도착하자 print가 되었다.

여기서 문제는 post() 함수는 기다리는 로직이 없고, 또한 asynchronous 데코도 없기때문에 로직이 끝나자 auto finish를 한것이다.


그럼 제대로 기다리려면 어떻게 해야할까? 방법은 2가지다.

1. @gen.coroutine 이용

    @gen.coroutine

    def post(self):

        res = yield self.test("test")

        print "done"


    @gen.coroutine

    def test(self, msg):

        print msg

        httpClient = AsyncHTTPClient()

        res = yield httpClient.fetch("http://www.naver.com")

        print res

        raise gen.Return(res)

yield를 써서 post함수 역시 test함수를 기다린다. 결과적으로 fetch를 기다리는것과 같다.

결과는

test

HTTPResponse

done

[web:1728] 200 POST /test (::1) 2.23ms (connection 종료, response 보냄)

이 된다.


2. @web.asynchronous 이용

이 경우에는 로직이 약간 변경된다. 기본적으로 post에서는 커넥션을 끊지 않을 뿐 post함수는 끝나고 단지 커넥션은 self.finish()를 요청하는곳에서 종료된다는것을 명시하는 것이다.

    @web.asynchronous    

    def post(self):

        self.test("test")


    @gen.coroutine

    def test(self, msg):

        print msg

        httpClient = AsyncHTTPClient()

        res = yield httpClient.fetch("http://www.naver.com")

        print res

        print "done"

        self.finish()

결과는 1번과 같다. 

'python > tornado' 카테고리의 다른 글

@web.asynchronous @gen.coroutine VS @gen.corutine  (0) 2014.04.10
블로그 이미지

시간을 거스르는자

ytkang86@gmail.com

,