게스트 게시물: 에릭 램버트
스파이멤캐시드 자바 클라이언트는 멤캐시드 서버를 이용해야 하는 자바 기반 애플리케이션에서 사용하는 대표적인 자바 클라이언트입니다. Spy가 Java 커뮤니티에서 큰 인기를 얻은 이유는 고도로 최적화되어 뛰어난 성능을 제공하면서도 사용자에게 과도한 복잡성 부담을 주지 않기 때문입니다.
가장 일반적인 경우 사용자는 다음 '템플릿'을 사용하기만 하면 됩니다. List servers = new ArrayList(); servers.add(new InetSocketAddress("192.168.0.9",11211); MemcachedClient client = new MemcachedClient(new BinaryConnectionFactory();, servers);
이 시점에서 멤캐시드 서버 클러스터에서 블라스팅 작업을 시작할 준비가 된 것입니다. Spy는 매우 간단하고 사용하기 쉬운 인터페이스를 제공하지만, 시스템 조정에 필요한 유연성을 희생하지는 않습니다. 그 이면에는 시스템을 조정할 수 있는 다양한 방법이 있습니다. 이 블로그에서는 Spy가 제공하는 몇 가지 노브와 스위치를 자세히 살펴봅니다. 이를 통해 Spy의 작동 방식과 기본 동작이 충분하지 않을 때 필요에 가장 적합하도록 조정하는 방법을 더 잘 이해하는 데 도움이 되기를 바랍니다. 하지만 본론으로 들어가기 전에 매우 간단하고 직관적이며 다소 순진한 Spymemcached 튜토리얼로 시작하여 다소 중요한 점을 설명하고자 합니다.
Spymemcached를 처음으로 평가하고 있고 일련의 설정, 가져오기, 삭제를 수행할 때 시스템이 어떻게 작동하는지 이해하고 싶다고 가정해 보겠습니다. 이를 위해 먼저 일련의 항목을 캐시에 설정한 다음 각 항목을 검색한 다음 마지막으로 각 항목을 삭제하는 간단한 프로그램을 만들 수 있습니다. 모든 설정, 가져오기, 삭제에 걸리는 총 시간을 추적하는 방식으로 이 작업을 수행하는 코드를 계측할 수 있습니다. 이를 위한 코드는 다음과 같이 보일 수 있습니다. // perform sets long start = System.nanoTime(); for (int i = 0; i < numberOfOps; i++) { client.set(KEY_PREFIX + i, 3600, PAY_LOAD).get(); } long end = System.nanoTime(); long setTime = end - start; // perform gets start = System.nanoTime(); for (int i = 0; i < numberOfOps; i++) { client.get(KEY_PREFIX + i); } end = System.nanoTime(); long getTime = end - start; // perform deletes start = System.nanoTime(); for (int i = 0; i < numberOfOps; i++) { client.delete(KEY_PREFIX + i).get(); } end = System.nanoTime(); long delTime = end - start; System.out.println(numberOfOps + " Set: " + setTime / nanosPerSec + " 평균: " + setTime / numberOfOps); System.out.println(numberOfOps + " Get: " + getTime / nanosPerSec + " 평균: " + getTime / numberOfOps); System.out.println(numberOfOps + " Delete: " + delTime / nanosPerSec + " 평균: " + delTime / numberOfOps);
앞서 언급했듯이 이것은 다소 순진하고 비현실적인 사용 사례입니다. 그럼에도 불구하고 이 조잡한 사례는 우리에게 중요한 교훈을 줍니다.
다른 값을 사용하여 이 테스트를 실행하면 어떤 결과가 나타나는지 살펴보겠습니다. numberOfOps
. 설정하면 numberOfOps
를 10,000으로 늘리면 다음과 같은 성과가 나타날 수 있습니다: 10000 세트: 3.008377 평균: 300837 10000 Get: 1.730886 평균: 173088 10000 삭제: 1.172679 평균: 117267
이제 한 단계 더 올라가서 numberOfOperations
를 10배로 늘리고 100,000으로 설정합니다: 100000 세트: 10.710224 평균: 107102 100000 가져오기: 9.992544 평균: 99925 100000 삭제: 9.876984 평균: 98769
흥미로운 점은 워크로드가 증가했음에도 불구하고 각 작업이 완료되는 데 걸리는 평균 시간이 실제로는 훨씬 짧아졌다는 것입니다. 설정 작업의 지연 시간은 거의 66% 감소했고, 가져오기 작업의 지연 시간은 거의 40%, 삭제 작업의 지연 시간은 15% 감소한 것을 확인할 수 있습니다. 이제 테스트에서 1,000,000개의 작업을 수행하면 어떤 결과가 나오는지 살펴보겠습니다. 1000000 세트: 106.15172 평균: 106151 1000000 Get: 101.086393 평균: 101086 1000000 삭제: 99.747647 평균: 99747
보시다시피, 1,000,000회 작업에서의 성능은 10,000회 작업에서의 성능보다 100,000회 작업에서의 성능과 훨씬 더 비슷해 보입니다.
이 불일치의 원인이 실제로 무엇인지에 대해서는 잠시 뒤로 미루고 여기서 더 중요한 교훈에 집중해 봅시다. 즉, 시스템의 동작과 성능을 이해하려고 할 때 시스템을 테스트할 때 사용하는 속성과 데이터 포인트가 가장 중요하다는 것입니다. 가능하면 이러한 값을 경험적으로 도출하거나 명시적으로 명시된 제약 조건이나 가정을 기반으로 해야 합니다. 위의 테스트를 실제로 Spymemcached 기반 시스템의 동작을 이해하기 위해 사용했다면 단순히 10,000개의 작업 시나리오를 사용해서는 시스템의 최고 성능을 파악할 수 없었을 것입니다. 100,000 또는 1,000,000 작업 시나리오만 실행했다면 시스템에 예열 시간이 필요한 것처럼 보인다는 사실을 놓쳤을 것입니다. 하지만 이 단순하고 순진한 테스트에서 흥미로운 값이 무엇인지 알아보기 위해 몇 가지 탐색을 수행함으로써 시스템에 대한 몇 가지 중요한 교훈을 얻었습니다.
이 이야기를 꺼내는 이유는 시스템의 성능과 동작에 대한 논의에서 임의의 값과 가정을 사용하는 것을 너무 자주 보기 때문입니다. 이런 경우를 보면 저자가 왜 특정 값을 선택했는지 궁금해집니다. 중요한 값이라면 그 값의 의미를 설명해야 합니다. 만약 임의의 값이라면 제시된 결과와 결론을 경계해야 합니다. (참고로, 위에 기록된 값은 클라이언트와 서버가 동일한 호스트에서 실행되는 memcached 1.4.4에 대해 Spymemcached 2.5를 사용하여 달성한 값입니다.)
일부 >br ;<.
그런데 이 블로그는 사이트 간 스크립팅에 취약한 것 같습니다.