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


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()쿼리 : Bar1Bar2데이터베이스에서 검색
  • Bar1.cache_key캐시에 이미 존재합니다 (2014-05-10) . 검색하여 출력
  • Bar2.cache_key 캐시에 (2014-05-16)이 없습니다
  • Bar2.todos.all()쿼리 : Bang3Bang4데이터베이스에서 검색
  • 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.