책임감있게 Redis하십시오

7579 단어 redisrubyrails
Redis는 속도에 관한 것입니다. 그러나 Redis가 빠르다고 해서 요청을 할 때 여전히 시간과 리소스를 사용하지 않는다는 의미는 아닙니다. 이러한 요청은 책임감 있게 이루어지지 않을 때 합산되어 애플리케이션의 성능에 영향을 미칠 수 있습니다. Kenna가 어떻게 이 교훈을 힘들게 배웠는지에 대한 이야기입니다.

잘 보이는 곳에 숨기



Kenna's 데이터베이스에서 가장 큰 테이블 중 하나는 취약점입니다. 현재 거의 40억이 있습니다. Avulnerability는 공격자가 컴퓨터 시스템에 대한 무단 액세스 권한을 얻기 위해 악용할 수 있는 약점입니다. 기본적으로 회사를 해킹할 수 있는 방법입니다.

우리는 초기에 이러한 모든 취약점을 우리의 정보 소스인 MySQL에 저장합니다. 여기에서 취약성 데이터를 Elasticsearch으로 인덱싱합니다.



이러한 모든 취약성을 Elasticsearch로 인덱싱할 때 Redis에 요청을 보내야 어디에 배치할지 알 수 있습니다. Elasticsearch에서 취약점은 클라이언트별로 구성됩니다. 취약점이 어디에 속하는지 파악하려면 해당 취약점에 대한 인덱스 이름을 가져오기 위해 Redis에 GET 요청을 해야 합니다.



인덱싱을 위해 취약점을 준비할 때 모든 취약점 해시를 수집합니다. 그런 다음 Elasticsearch로 보내기 전에 마지막으로 수행하는 작업 중 하나는 Redis GET 요청을 만들어 클라이언트를 기반으로 각 취약점에 대한 인덱스 이름을 검색하는 것입니다.

indexing_hashes = vulnerability_hashes.map do |hash|
   {
      :_index => Redis.get("elasticsearch_index_#{hash[:client_id]}")
      :_type => hash[:doc_type],
      :_id => hash[:id],
      :data => hash[:data]
   }
end


이러한 취약성 해시는 클라이언트별로 그룹화되므로 GET 요청

Redis.get("elasticsearch_index_#{hash[:client_id]}")


동일한 정보를 반복해서 반환하는 경우가 많습니다. 이러한 모든 간단한 GET 요청은 맹목적으로 빠릅니다. 실행하는 데 약 1밀리초가 걸립니다.

(pry)> index_name = Redis.get("elasticsearch_index_#{client_id}")
DEBUG -- : [Redis] command=GET args="elasticsearch_index_1234"
DEBUG -- : [Redis] call_time=1.07 ms


그러나 외부 요청이 얼마나 빠른지는 중요하지 않습니다. 요청을 많이 하면 시간이 오래 걸릴 것입니다. 우리는 이러한 간단한 GET 요청을 너무 많이 만들었기 때문에 인덱싱 작업 실행 시간의 약 65%를 담당했습니다. 아래 표에서 이 통계를 볼 수 있으며 그래프에서 갈색으로 표시됩니다.



이러한 많은 요청을 제거하는 솔루션은 로컬 Ruby 캐시였습니다! 결국 Ruby 해시를 사용하여 각 클라이언트의 Elasticsearch 인덱스 이름을 캐시했습니다.

client_indexes = Hash.new do |h, client_id| 
   h[client_id] = Redis.get("elasticsearch_index_#{client_id}")
end



그런 다음 모든 취약성 해시를 반복하여 Elasticsearch로 보낼 때 각 취약성에 대해 Redis를 누르는 대신 이 클라이언트 인덱스 해시를 참조하기만 하면 됩니다.

indexing_hashes = vuln_hashes.map do |hash|
   {
      :_index => client_indexes[hash[:client_id]]
      :_type => hash[:doc_type],
      :_id => hash[:id],
      :data => hash[:data]
   }
end


즉, 취약점당 한 번이 아니라 클라이언트당 한 번만 Redis를 공격해야 했습니다.

보수



인덱싱해야 하는 취약점 배치가 3개 있다고 가정해 보겠습니다.



이 세 배치의 경우 각 배치에 얼마나 많은 취약점이 있든 관계없이 Redis에 총 3개의 요청만 하면 됩니다. 이러한 배치에는 일반적으로 각각 1,000개의 취약점이 포함되어 있으므로 이 변경으로 인해 Redis에 대한 히트가 1000배 감소하여 작업 속도가 65% 증가했습니다.

Redis가 빠르지만 로컬 캐시를 사용하는 것이 항상 더 빠릅니다! 관점에서 보자면 로컬 캐시에서 정보를 얻는 것은 정보를 얻기 위해 시카고 시내에서 오헤어 공항까지 운전하는 것과 같습니다.



Redis에서 동일한 정보를 얻는 것은 마치 시카고에서 비행기를 타고 보스턴까지 날아가서 정보를 얻는 것과 같습니다.



Redis는 너무 빨라서 대화할 때 실제로 외부 요청을 하고 있다는 사실을 잊기 쉽습니다. 이러한 외부 요청은 합산되어 애플리케이션의 성능에 영향을 미칠 수 있습니다. Redis를 당연시 여기지 마십시오. 귀하가 요청하는 모든 요청이 절대적으로 필요한지 확인하십시오.

Ruby를 사용하여 데이터베이스 적중을 방지하는 다른 방법에 관심이 있다면 이 게시물에 영감을 준 RubyConf의 내 연설Cache Is King을 확인하십시오.

좋은 웹페이지 즐겨찾기