redis 03 springboot 快取
阿新 • • 發佈:2021-06-28
Something before start
主要解決兩種快取場景
1、實時更新的快取 即一般的查詢時候,把記錄寫進快取。
2、不需要實時的快取 即不需要很準確的資料//比如使用者數量什麼的。對於這種情況,需要注意快取雪崩的問題。這裡是使用雙重檢測鎖來解決這個問題的。
快取雪崩:資料到期,大量請求湧入到資料庫
依賴
<!--redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
配置檔案
連線redis
有三種形式連線。另外注意配置redis的配置檔案
# 關閉保護模式
protected-mode no
# 把這個註釋掉,開啟外地連線
#bind
單機
spring.redis.host=127.0.0.1
spring.redis.port=6379
#spring.redis.password=
哨兵模式叢集
# 這個mymaster 可以直接在sentinel.conf裡找到,可以更換成自己喜歡的hhhh spring.redis.sentinel.master=mymaster # 這裡展示的是多種寫法,多個哨兵 spring.redis.sentinel.nodes=locathost:26379,127.0.0.1:26380,locathost:26381 spring.redis.sentinel.password=
cluster叢集
# 連線redis叢集 //cluster模式
spring.redis.cluster.nodes=127.0.0.1:7006,127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005
#spring.redis.password=
指定springboot快取形式
# 指定cache型別
spring.cache.type=redis
# 快取區域名稱 //隨便取都行 同時可以多快取空間
spring.cache.cache-names=realTimeCache
實體類序列化
很簡單,只要實現java的序列化介面就行Serializable
序列化簡單理解就是把一個物件轉化成字元流
public class Employee implements Serializable {
private Integer id;
private String name;
private int age;
//省略其他亂七八糟的東西
註解方式
怎麼確保快取準確性
每次更新資料的時候就清理所有的快取,在查詢的時候將資料時寫入快取。因為redis本身效能很高,所以不用擔心效能啥的。
啟動類開啟快取
@EnableCaching
開啟快取
@EnableCaching
@EnableTransactionManagement
@SpringBootApplication
public class RedisdemoApplication {
更新資料 清理快取
@CacheEvict
: 放在更新(增刪改)資料的方法上
- value是前面配置的快取區域名稱。
- 當註解引數加上allEntries為true時,意思是說這個清除快取是清除當前value值空間下的所有快取資料。
//更新資料 則 更新清理快取
@CacheEvict(value = "realTimeCache", allEntries = true)
@PostMapping("regist")
public void registHandle(Employee employee) {
employeeService.regist(employee);
}
查詢資料 更新快取
@Cacheable
:放在查詢的方法上
//value:快取空間 key:鍵
@Cacheable(value = "realTimeCache", key = "'emloyee_'+#id")
@GetMapping("find")
public Employee findHandle(int id) {
return employeeService.findEmployeeById(id);
}
API方式
什麼是雙重檢測鎖
第一次檢測:進入方法,如果有值則返回,如果取出來為空則開啟同步阻塞其他執行緒請求。
第二次檢測:進入同步執行緒之後,再次檢測是否有值,有則返回,無則將請求送到資料庫。
為什麼需要第二次檢測:第一取不到值的執行緒進入同步的時候,可能會有其他請求跑進來。第一個執行緒更新完之後,其他的執行緒就不許要重新更新,所以需要第二次檢測
實現程式碼
//使用雙重檢測鎖 解決 熱點快取問題
@GetMapping("count")
public Integer countHandle() {
//獲取redis操作物件 和count繫結 count即key
BoundValueOperations<Object, Object> ops = redisTemplate.boundValueOps("count");
//從快取中獲得資料
Object count = ops.get();
if (count==null){
//因為上鎖之後阻塞了 會有新的請求到這裡,所以需要上鎖後重新檢測保證後面來的不會擊穿
//因為是單例 所以可以用this
synchronized (this){
count = ops.get();
if (count==null){
count = employeeService.findEmployeeCount();
ops.set(count,10, TimeUnit.SECONDS);//存入 存活10秒
}
}
}
return (Integer)count;
}
自動生成key
一樣是使用codeConfig方式。
然後就可以把註解裡的那個key刪掉了
注意這裡的para只適合一個引數的情況//其實寫一個迴圈就完事了
暫時懶得寫解釋,感性理解一下就好/
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {
//自動生成key結構:類名_方法名_引數
@Override
public KeyGenerator keyGenerator() {
return (target,method,params)->{
String className = target.getClass().getName();
String methodName = method.getName();
return className+"-"+methodName+"-"+params[0].toString();
};
}
}