키 기반 캐싱은 어떻게 작동합니까?


10

최근에 37Signals 블로그 에서 기사를 읽었 으며 캐시 키를 얻는 방법이 궁금합니다.

객체의 타임 스탬프를 포함하는 캐시 키를 갖는 것이 좋습니다. 이는 객체를 업데이트 할 때 캐시가 무효화됨을 의미합니다. 그러나 캐시에서 가져 오려는 객체에 대한 DB 적중을 유발하지 않고 템플릿에서 캐시 키를 어떻게 사용합니까?

특히, 이는 예를 들어 게시물의 주석을 렌더링하는 일대 다 관계에 어떤 영향을 미칩니 까?

장고의 예 :

{% for comment in post.comments.all %}
   {% cache comment.pk comment.modified %}
     <p>{{ post.body }}</p>
   {% endcache %}
{% endfor %}

Rails에서 캐싱하는 것은 예를 들어 memcached에 대한 요청과 다릅니다 (캐시 키를 다른 것으로 변환한다는 것을 알고 있습니다). 캐시 키도 캐시합니까?


Django 예제 는 rossp.org/blog/2012/feb/29/fragment-caching 을 보십시오 !
— vdboor

나는 이미 그것을 보았고 정확히 같은 문제로 고통받는 것 같습니다. 캐시에 액세스하려면 캐시에 액세스하려는 데이터가 필요합니다. 그가 절약 할 수있는 유일한 것은이 유형의 캐싱에 대한 대부분의 유스 케이스와 달리 비싼 내부 작업에 있습니다.
— Dominic Santos

사실, 37 신호 코드에서도 발생하며 렌더링 코드에 중점을 둡니다. 요령은 전체 목록을 다른 컨테이너에 캐시하거나 다른 곳에서 객체 검색을 캐시하는 것입니다.
— vdboor

실제로 그들의 캐싱 전략은 조금 더 교육적인 것으로 보입니다. 이 기사도 추천합니다 : 37signals.com/svn/posts/…
— JensG

그것은 당신의 코드는 오타가 보이는 - 한 post.body의도 comment.body?
— 이즈 카타

답변:


3

이미로드 된 단일 객체의 스트레이트 덤프를 캐싱하려면 아무것도 얻거나 아무것도 얻지 못합니다. 그것은 그 예들이 묘사하는 것이 아닙니다. 그것들은 계층 구조를 설명하고 있습니다. 하위 계층에 대한 변경은 계층 구조에서 상위에있는 모든 것에 대한 업데이트를 유발해야합니다.

37signals 블로그의 첫 번째 예 Project -> Todolist -> Todo는 계층 구조로 사용 됩니다. 채워진 예제는 다음과 같습니다.

Project: Foo (last_modified: 2014-05-10)
   Todolist:  Bar1 (last_modified: 2014-05-10)
       Todo:  Bang1 (last_modified: 2014-05-09)
       Todo:  Bang2 (last_modified: 2014-05-09)

   Todolist:  Bar2 (last_modified: 2014-04-01)
       Todo:  Bang3 (last_modified: 2014-04-01)
       Todo:  Bang4 (last_modified: 2014-04-01)

따라서 Bang3업데이트 되었다고 가정 해 봅시다 . 모든 부모님도 업데이트됩니다.

Project: Foo (last_modified: 2014-05-16)
   Todolist:  Bar2 (last_modified: 2014-05-16)
       Todo:  Bang3 (last_modified: 2014-05-16)

그런 다음 렌더링 할 때 Project데이터베이스에서 로드 하는 것이 불가피합니다. 시작해야 할 점이 필요합니다. 그러나 이는 모든 하위 항목last_modified 의 표시기 이므로 하위 항목 을로드하기 전에 캐시 키로 사용합니다.


블로그 게시물은 별도의 템플릿을 사용하지만 템플릿을 하나로 묶습니다. 한곳에서 완전한 상호 작용을 보는 것이 조금 더 명확 해지기를 바랍니다.

따라서 Django 템플릿은 다음과 같습니다.

{% cache 9999 project project.cache_key %}
<h2>{{ project.name }}<h2>
<div>
   {% for list in project.todolist.all %}
   {% cache 9999 todolist list.cache_key %}
      <ul>
         {% for todo in list.todos.all %}
            <li>{{ todo.body }}</li>
         {% endfor %}
      </ul>
   {% endcache %}
   {% endfor %}
</div>
{% endcache %}

cache_key캐시에 여전히 존재 하는 프로젝트를 전달한다고 가정 해보십시오 . 모든 관련 객체에 대한 변경 사항을 부모에게 전파하기 때문에 특정 키가 여전히 존재한다는 사실은 렌더링 된 전체 내용 을 캐시에서 가져올 수 있음을 의미합니다 .

특정 프로젝트가 방금 업데이트 된 경우 (예 : Foo위와 같이) 자식을 렌더링해야하며, 그런 다음에 만 해당 프로젝트의 모든 Todolist에 대한 쿼리를 실행합니다. 특정 Todolist의 경우와 마찬가지로-해당 목록의 cache_key가 있으면 목록 내의 할 일이 변경되지 않으며 캐시에서 전체 항목을 가져올 수 있습니다.

todo.cache_key이 템플릿에서 어떻게 사용 하고 있지 않은지 확인 하십시오. 질문에서 말했듯 body이 이미 데이터베이스에서 가져온 것이기 때문에 그만한 가치가 없습니다 . 그러나 데이터베이스 적중이 캐시하는 유일한 이유는 아닙니다. 예를 들어, 원시 마크 업 텍스트 (예 : StackExchange의 질문 / 응답 상자에 입력 한 내용)를 HTML로 변환하면 결과를 캐싱하는 것이 더 효율적일 수 있습니다.

그렇다면 템플릿의 내부 루프가 다음과 같이 보일 수 있습니다.

         {% for todo in list.todos.all %}
            {% cache 9999 todo todo.cache_key %}
               <li>{{ todo.body|expensive_markup_parser }}</li>
            {% endcache %}
         {% endfor %}

모든 것을 하나로 모으기 위해이 답변의 맨 위에서 원래 데이터로 돌아가 보겠습니다. 우리가 가정한다면 :

  • 모든 객체가 원래 상태로 캐시되었습니다
  • Bang3 방금 업데이트되었습니다
  • 우리는 (를 포함하여 수정 된 템플릿을 렌더링하고 expensive_markup_parser)

그런 다음 모든 것이로드되는 방법입니다.

  • Foo 데이터베이스에서 검색
  • Foo.cache_key 캐시에 (2014-05-16)이 없습니다
  • Foo.todolists.all()쿼리 : Bar1및 Bar2데이터베이스에서 검색
  • Bar1.cache_key캐시에 이미 존재합니다 (2014-05-10) . 검색하여 출력
  • Bar2.cache_key 캐시에 (2014-05-16)이 없습니다
  • Bar2.todos.all()쿼리 : Bang3및 Bang4데이터베이스에서 검색
  • Bang3.cache_key 캐시에 (2014-05-16)이 없습니다
  • {{ Bang3.body|expensive_markup_parser }} 렌더링
  • Bang4.cache_key(2014-04-01)이 이미 캐시에 존재합니다 . 검색하여 출력

이 작은 예제에서 캐시를 절약하면 다음과 같습니다.

  • 데이터베이스 적중 방지 : Bar1.todos.all()
  • expensive_markup_parser피 3 회 : Bang1, Bang2, 및Bang4

물론 다음에 볼 때는 데이터베이스에서 단독으로 Foo.cache_key검색 Foo하고 캐시를 쿼리하는 데 드는 유일한 비용 입니다.


-2

각 주석마다 데이터를 검색하거나 처리해야하는 경우에 좋습니다. 본문을 가져 와서 표시하면 캐시가 쓸모가 없습니다. 그러나 모든 주석 트리 ({% for %} 포함)를 캐시 할 수 있습니다. 이 경우 추가 된 모든 주석으로 주석을 무효화해야하므로 마지막 주석 타임 스탬프 또는 주석 수를 Post에 넣고 주석 캐시 키를 작성하십시오. 보다 표준화 된 데이터를 선호하고 한 페이지에서만 주석을 사용하는 경우 주석 저장시 캐시 키를 지우면됩니다.

나를 위해, 게시물에 메모 수를 저장하면 충분하게 보입니다 (댓글을 삭제하고 편집 할 수없는 경우). 포스트와 캐싱 키를 사용하여 어디서나 표시 할 수있는 값이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.