簡體   English   中英

Spring 啟動 Redis 緩存刪除緩存與多鍵

[英]Spring Boot Redis Cache remove cache with multiple key

我有一種保存緩存的方法。

@GetMapping("/orders")
@Cacheable(value = "List<Order>", key = "{#customerName+'s orders', #page, #size}")
public List<Order> findOrders(@RequestParam("customerName") String customerName,
                              @RequestParam(name = "page") int page,
                              @RequestParam(name = "size") int size) {
...

我想在調用這個方法后刪除這個緩存。

@PostMapping("/order")
@CacheEvict(value = "*",key="{#makeOrderDTO.customerDTO.name+'s orders', '', 'regex:*'}")
public Order makeOrder(@RequestBody MakeOrderDTO makeOrderDTO) {

我有一個問題,我想刪除客戶的所有緩存頁面,但我不能只刪除一種類型的頁面。 所以我需要刪除所有頁面大小和數量的客戶。 也許有某種功能,例如

@PostMapping("/order")
@CacheEvict(value = "*",key="{#makeOrderDTO.customerDTO.name+'s orders', 'regex:*', 'regex:*'}")
public Order makeOrder(@RequestBody MakeOrderDTO makeOrderDTO) {

或者

@PostMapping("/order")
@CacheEvict(value = "*",key="{#makeOrderDTO.customerDTO.name+'s orders', 'any', 'any'}")
public Order makeOrder(@RequestBody MakeOrderDTO makeOrderDTO) {

提前致謝。


你不能這樣做,因為所有緩存技術都使用鍵值存儲。 因此,如果您對鍵使用多個參數,如下所示:

key = "{#customerName+'s orders', #page, #size}"

Spring 創建一個 hash 作為密鑰,例如:-172893112。

參考: https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/cache.html#cache-annotations-cacheable-default-key

我建議您將緩存名稱更改為使用“'List' + #customerName+'s orders'”,但至少使用 CacheResolver 時不支持使用注釋。 這里

@GetMapping("/orders")
@Cacheable(value = "List<Order>", key = "{#customerName+'s orders', #page, #size}")
public List<Order> findOrders(@RequestParam("customerName") String customerName, @RequestParam(name = "page") int page, @RequestParam(name = "size") int size) {
  //...
  List<Order> result = //...Do the operation
  String cacheName = "List<Order>" + customerName + "s orders";
  redisTemplate
    .opsForHash()
    .put(cacheName, Objects.hash(customerName, page, size), result);
}

之后,驅逐方法應該是:

@PostMapping("/order")
public Order makeOrder(@RequestBody MakeOrderDTO makeOrderDTO) {
  String cacheName = "List<Order>" + makeOrderDTO.getCustomerDTO().getName() + "s orders";
  redisTemplate
    .opsForHash()
    .keys(cacheName)
    .forEach(x -> redisTemplate.opsForHash().delete(cacheName, x));

  //...Do operations
}

您可以查看另一個帖子: Cache evict on one of multiple keys

查看您的初始方法:

@GetMapping("/orders")
@Cacheable(value = "List<Order>", key = "{#customerName+'s orders', #page, #size}")
public List<Order> findOrders(@RequestParam("customerName") String customerName,
                              @RequestParam(name = "page") int page,
                              @RequestParam(name = "size") int size) {
...

從簽名猜測,該方法做了很多事情:

  • 從某處檢索訂單
  • 做一些分頁
  • 提供REST接口

如果分頁參數不同,您可能會多次檢索和緩存相同的訂單。 下新訂單后,您需要重新閱讀未更改的先前訂單。 那是次優的。

我建議將數據訪問和緩存數據的關注點分開,並在兩個類或層中為 web 請求提供服務,因為 web 層位於數據訪問層之上。

此外,始終使用 id 而不是客戶名稱作為鍵,因為名稱可能有重復並且也會發生變化(是的,錯字。婚姻和公司合並)。

對於緩存查詢結果,我總是建議分別緩存查詢結果和數據。 例如,在您的數據訪問層中:

public List<Integer> findOrders(int customerId);
public Order retrieveOrder(int orderId);

為它使用兩個單獨的緩存。

然后,您可以在 REST 層中實現分頁。

public Order makeOrder(MakeOrderDTO makeOrderDTO)

下新訂單時,訂單列表查詢結果無效。 您可以添加 ID,也可以使用 evict 使查詢結果緩存無效。 但是,這不會影響帶有實際訂單數據的緩存。

我省略了實際的 Spring 緩存注釋。 一旦您對界面進行了排序,這些界面就應該簡單明了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM