페이지가 매겨진 결과 캐싱, 업데이트 시 제거 - 해결 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/109480

문제

저는 포럼을 만들었고 데이터베이스 작업을 절약하기 위해 apc 및 memcache 캐싱 솔루션을 구현하고 있습니다.

저는 "Categories::getAll"과 같은 키를 사용하여 캐시 레이어를 구현하기 시작했습니다. 사용자별 데이터가 있는 경우 사용자 ID와 같은 항목을 키에 추가하면 다음과 같은 결과를 얻을 수 있습니다. "User::getFavoriteThreads|1471".사용자가 즐겨찾는 새 스레드를 추가하면 캐시 키를 삭제하고 해당 항목이 다시 생성됩니다.

그러나 여기에 문제가 있습니다.

포럼의 스레드를 캐시하고 싶었습니다.매우 간단합니다. "Forum::getThreads|$iForumId"입니다.하지만...페이지 매김을 사용하면 이를 여러 캐시 항목으로 분할해야 합니다. 예를 들어

"Forum::getThreads|$iForumId|$iLimit|$iOffset".

누군가가 포럼에 새 스레드를 게시하기 전까지는 괜찮습니다.이제 아래의 모든 키를 삭제해야 합니다. "Forum::getThreads|$iForumId", 한계와 오프셋이 무엇이든 관계 없습니다.

이 문제를 해결하는 좋은 방법은 무엇입니까?더 이상 일치하지 않는 것을 찾을 때까지 가능한 모든 한계와 오프셋을 반복하지 않는 것이 좋습니다.

감사해요.

도움이 되었습니까?

해결책

또한 노력과 CPU 비용 측면에서 캐시 데이터를 저장하는 비용과 캐시를 통해 얻을 수 있는 비용을 살펴보고 싶을 수도 있습니다.

포럼 조회수의 80%가 스레드의 첫 번째 페이지를 보고 있는 경우 해당 페이지만 캐시하도록 결정할 수 있습니다.이는 캐시 읽기와 쓰기 모두 구현하기가 훨씬 간단하다는 것을 의미합니다.

사용자가 즐겨찾는 스레드 목록도 마찬가지입니다.각 사람이 거의 방문하지 않는 경우 캐시는 성능을 크게 향상시키지 못할 수 있습니다.

다른 팁

업데이트 사항:나는 데이터 사용에 대한 Josh의 의견이 매우 좋다고 판단했습니다.사람들이 포럼의 50페이지를 계속해서 볼 가능성은 없습니다.

이 모델을 기반으로 각 포럼의 최신 스레드 90개를 캐시하기로 결정했습니다.가져오기 기능에서 지정된 스레드 조각이 캐시 내에 있는지 여부를 확인하기 위해 제한과 오프셋을 확인합니다.캐시 제한 내에 있으면 array_slice()를 사용하여 올바른 부분을 검색하고 반환합니다.

이렇게 하면 포럼당 단일 캐시 키를 사용할 수 있으며 캐시를 지우거나 업데이트하는 데 거의 노력이 필요하지 않습니다. :-)

또한 리소스가 많은 다른 쿼리에서는 키 간의 관계를 저장하는 flungabunga 모델을 사용했다는 점을 지적하고 싶습니다.불행하게도 스택 오버플로에서는 두 가지 답변을 받아들일 수 없습니다.

감사해요!

확장을 통해 이 문제를 해결했습니다. memcache 키 값에 대한 그룹의 해시 테이블을 포함하는 보호 속성이 있는 사용자 정의 클래스(예: ExtendedMemcache)가 있는 클래스입니다.

그만큼 ExtendedMemcache->set 메소드는 3개의 인수를 허용합니다($strGroup,$strKey, $strValue) 세트를 호출 할 때, 그것은 간의 관계를 저장합니다. $strGroup, 그리고 $strKey, 보호된 속성에 저장한 다음 계속해서 $strKey 에게 $strValue 관계 memcache.

그런 다음 새 메소드를 추가할 수 있습니다. ExtendedMemcache "deleteGroup"이라는 클래스는 문자열이 전달되면 해당 그룹과 연결된 키를 찾아 차례로 각 키를 제거합니다.

다음과 같을 것입니다:http://pastebin.com/f566e913b모든 것이 이해가 되고 효과가 있기를 바랍니다.

추신.정적 호출을 사용하고 싶다면 보호 속성을 다음 위치에 저장할 수 있다고 가정합니다. memcache 그 자체는 자신의 키 아래에 있습니다.그냥 생각입니다.

본질적으로 뷰를 캐시하려고 하는데 이는 항상 까다로워집니다.데이터는 거의 변경되지 않으므로 대신 데이터만 캐시해야 합니다.포럼을 캐시하지 말고 스레드 행을 캐시하세요.그런 다음 db 호출은 이미 캐시에 있는 ID 목록을 반환해야 합니다.db 호출은 모든 MyISAM 테이블에서 빠르게 진행되므로 db 메모리를 소모하는 대규모 조인을 수행할 필요가 없습니다.

한 가지 가능한 해결책은 포럼의 스레드 캐시에 페이지를 매기는 것이 아니라 스레드 정보를 포럼에 넣는 것입니다. Forum::getThreads|$iForumId.그런 다음 PHP 코드에서 해당 페이지에 대해 원하는 항목만 가져옵니다.

$page = 2;
$threads_per_page = 25;
$start_thread = $page * $threads_per_page;

// Pull threads from cache (assuming $cache class for memcache interface..)
$threads = $cache->get("Forum::getThreads|$iForumId");

// Only take the ones we need
for($i=$start_thread; $i<=$start_thread+$threads_per_page; $i++)
{
    // Thread display logic here...
    showThread($threads[$i]);
}

즉, 각 페이지에서 캐시를 꺼내는 작업이 조금 더 필요하지만 이제 새 스레드를 업데이트/추가할 때 한 곳에서 캐시를 무효화하는 것에 대해서만 걱정하면 됩니다.

플런가분가:귀하의 솔루션은 제가 찾고 있는 솔루션과 매우 가깝습니다.이 작업을 수행하지 못하게 하는 유일한 방법은 각 요청 후에 Memcache에 관계를 저장하고 다시 로드해야 한다는 것입니다.

이것이 얼마나 많은 성능 저하를 의미하는지 잘 모르겠지만 약간 비효율적인 것 같습니다.나는 몇 가지 테스트를 수행하고 그것이 어떻게 진행되는지 볼 것입니다.구조화된 제안에 감사드립니다(그리고 이를 표시할 코드도 있습니다!).

측정할 확실한 사실 없이 이러한 종류의 최적화를 수행할 때는 매우 주의하십시오.

대부분의 데이터베이스에는 여러 수준의 캐시가 있습니다.이것이 올바르게 조정되면 데이터베이스는 아마도 사용자가 직접 수행할 수 있는 것보다 캐싱 작업을 훨씬 더 잘 수행할 것입니다.

flungabunga에 대한 응답:

그룹화를 구현하는 또 다른 방법은 그룹 이름과 시퀀스 번호를 키 자체에 넣고 시퀀스 번호를 증가시켜 그룹을 "삭제"하는 것입니다.각 그룹의 현재 유효한 시퀀스 번호를 자체 키에 저장합니다.

예를 들어

get seqno_mygroup
23

get mygroup23_mykey
<mykeydata...>
get mygroup23_mykey2
<mykey2data...>

그런 다음 그룹을 "삭제"하려면 다음을 수행하십시오.

incr seqno_mygroup

짜잔:

get seqno_mygroup
24

get mygroup24_mykey
...empty

등..

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top