給webflux增加緩存

上一篇中已經給用戶管理增加了頁面,看上去比較low,但是不犯該大家學習。今天增加redis來作爲緩存。

1 爲什麼要做緩存

當用戶訪問量增大的時候,併發量也會增大,同一時間數據庫查詢的壓力也會增大。儘管mongodb的查詢速度已經很快了,但是也會出現性能瓶頸,一般會通過集羣來解決。另一方面就是增加緩存,使得不用每次查詢都要經過數據庫。提高響應速度。

2 緩存策略

  • 在查詢方法中先從緩存中取,如果沒有則查詢數據庫
  • 在刪除方法中,同時刪除緩存中的值
  • 在更新操作中,同步修改緩存中的值

3 添加依賴

關於redis的安裝,我之前的文章中已經講過了,可關注我的公衆號mike啥都想搞在教程中查看。補充:
之前我們講了如和設置redis的密碼,可是都不生效。是因爲啓動方式不對,需要指定備至文件

redis-server.exe redis.windows.conf
        <!-- Spring Boot 響應式 Redis 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>

設置redis連接:

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=mike123
spring.redis.timeout=5000

4 改造service中的方法

package com.mike.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import com.mike.dao.UserDao;
import com.mike.po.User;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * The class UserService.java
 */
@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    
    @Autowired
    private RedisTemplate redisTemplate;
    
    @Autowired
    private MongoTemplate mongoTemplate;
    
    public Mono<User> saveOrUpdateUser(User user){
        //刪除緩存
        if (redisTemplate.hasKey("user_"+user.getId())) {
            redisTemplate.delete("user_"+user.getId());
        }
        return userDao.save(user);
    }
    
    public Mono<User> findById(String id){
        redisTemplate.opsForValue().set("test","test");
        //先查找緩存
        boolean hashKey = redisTemplate.hasKey("user_"+id);
        if (hashKey) {
            User u = (User) redisTemplate.opsForValue().get("user_"+id);
            return Mono.create(rs -> rs.success(u));
        }
        Mono<User> m = userDao.findById(id);
        if (m!=null) { //更新緩存
            m.subscribe(u -> {
                redisTemplate.opsForValue().set("user_"+u.getId(), u);
            });
        }
        return m;
    }
    
    public Flux<User> findAll(){
        return userDao.findAll().cache();
    }
    
    public  void deleteById(String id){
        // 使用mongoTemplate來做刪除   直接使用提供的刪除方法不行
        Query query = Query.query(Criteria.where("id").is(id));
        mongoTemplate.remove(query, User.class);
        //userDao.deleteById(id);  這樣無法刪除,不知道爲什麼
        
        //同時刪除緩存
        if (redisTemplate.hasKey("user_"+id)) {
            redisTemplate.delete("user_"+id);
        }
    }
}

總結

一般我們會和@cacheable註解配合使用,但是在webflux中,我們需要手動編程來實現redis的數據存儲。原因是Mono / Flux 對象沒有實現 Serializable。上面用的是同步操作redis,還有一個異步操作ReactiveRedisTemplate,但是因爲我們操作緩存的時候要先進行key的判斷後在執行後續操作,這是同步過程。使用ReactiveRedisTemplate的話感覺操作比較麻煩,誰如果有好的寫法可以一起交流下。

填坑: User 對象需要實現Serializable,否則redis存儲會失敗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章