페이지네이션 적용된 캐시데이터 한번에 삭제하기

2024. 7. 10. 21:31TIL

✔오늘 배운 중요한 🔑 point

  • @CacheEvict는 단일 키에 대해서만 작동하며, 와일드카드나 패턴 매칭을 지원하지 않는다.
  • redisTemplate를 이용해서 특정 패턴에 대한 키를 삭제할 수 있다.

🎯 오늘 배운 내용

 

페이지네이션이 적용된 캐시 keywordPostCache::breedName-0-10, keywordPostCache::breedName-1-10 등을 같이 삭제하기 위해서 해당 코드를 작성하였다.  

@CacheEvict( value = ["keywordPostCache"], key ="#breedName + '*' ")
    fun evictCaches(postId: Long, breedName: String){
        logger.info("해당 견종 캐시 삭제 : $breedName")
    }

하지만 내 예상대로 삭제가 진행되지는 않았다.

 

@CacheEvict는 단일 키에 대해서만 작동하며, 와일드카드나 패턴 매칭을 지원하지 않기 때문에 @CacheEvict를 사용하여 특정 패턴에 맞는 모든 캐시 엔트리를 삭제하는 것은 불가능하다고 한다.

 

따라서 redisTemplate를 이용해서 특정 패턴에 맞는 캐시를 지우는 방법을 선택하였다.

package com.teamsparta.withdog.infra.redis

import org.slf4j.LoggerFactory
import org.springframework.cache.annotation.CacheEvict
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.stereotype.Component


@Component
class EvictCache(
    private val redisTemplate: RedisTemplate<String, String>
) {
    private val logger = LoggerFactory.getLogger(this.javaClass)


    fun evictCaches(breedName: String) {
        logger.info("해당 견종 캐시 삭제 : $breedName")
        val keys = redisTemplate.keys("keywordPostCache::$breedName*")
        if (!keys.isNullOrEmpty()) {
            redisTemplate.delete(keys)
            logger.info("삭제된 키들: $keys")
        } else {
            logger.info("삭제할 키가 없습니다.")
        }
    }

    @CacheEvict( value = ["keywordPostCache"], key ="#breedName")
    fun evictCaches(postId: Long, breedName: String){
        logger.info("해당 견종 캐시 삭제 : $breedName")
    }

}

 

 

 

@Caching(
    evict = [
        CacheEvict(value = ["postCache"], key = "#postId"),
    ]
)
@Transactional
fun deletePost(
    postId: Long,
    userId: Long
) {
    val post = postRepository.findByIdOrNull(postId)
        ?: throw ModelNotFoundException("삭제된 게시글 입니다.")

    if (post.isDeleted)
        throw ModelNotFoundException("삭제된 게시글 입니다.")

    if (userId != post.user.id)
        throw UnauthorizedException("권한이 없습니다.")

    evictCache.evictCaches(breedName = post.breedName, postId = postId)
    evictCache.evictCaches(breedName = post.breedName)
    post.imageUrl?.let { s3Service.delete(it.split("m/")[1]) }
    post.softDeleted()
    likeService.deleteLike(post)


}
evictCache.evictCaches(breedName = post.breedName, postId = postId)
evictCache.evictCaches(breedName = post.breedName)

해당 부분을 추가하여 기존의 postCache와 페이지네이션으로 등록이 된 keywordPostCache 를 한번에 삭제할 수 있게 되었다.

🤔 어떻게 활용할까?

redisTemplate를 이용해서 특정패턴의 캐시를 한번에 삭제할 수있다.

📓 오늘의 한줄

"Energy and persistence conquer all things."

- Benjamin Franklin -