SpringSession+redis解決分佈式session不一致性問題

七、案例實戰:SpringSession+redis解決分佈式session不一致性問題

步驟1:加入SpringSession、redis的依賴包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

步驟2:修改配置文件


# 爲某個包目錄下 設置日誌
logging.level.com.agan=debug


# 設置session的存儲方式,採用redis存儲
spring.session.store-type=redis

# session有效時長爲10分鐘
server.servlet.session.timeout=PT10M

## Redis 配置
## Redis數據庫索引(默認爲0)
spring.redis.database=0
## Redis服務器地址
spring.redis.host=192.168.1.138
## Redis服務器連接端口
spring.redis.port=6379
## Redis服務器連接密碼(默認爲空)
spring.redis.password=

八、剖析SpringSession的redis原理

步驟1:分析SpringSession的redis數據結構

127.0.0.1:6379> keys *
1) "spring:session:expirations:1578227700000"
2) "spring:session:sessions:5eddb9a3-5b1e-4bdd-a289-394b6d42388e"
3) "spring:session:sessions:expires:5eddb9a3-5b1e-4bdd-a289-394b6d42388e"

共同點:3個key都是以spring:session:開頭的,代表了SpringSession的redis數據。
“spring:session:sessions:5eddb9a3-5b1e-4bdd-a289-394b6d42388e”

127.0.0.1:6379> type "spring:session:sessions:5eddb9a3-5b1e-4bdd-a289-394b6d42388e"
hash

127.0.0.1:6379> hgetall “spring:session:sessions:5eddb9a3-5b1e-4bdd-a289-394b6d42388e”

//失效時間 100分鐘

  1. “maxInactiveInterval”
  2. “\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x17p”

// sesson的屬性,存儲了user對象
3) “sessionAttr:5eddb9a3-5b1e-4bdd-a289-394b6d42388e”
4) “\xac\xed\x00\x05sr\x00\x1ecom.agan.redis.controller.User\x16”_m\x1b\xa0W\x7f\x02\x00\x03I\x00\x02idL\x00\bpasswordt\x00\x12Ljava/lang/String;L\x00\busernameq\x00\x00\x01xp\x00\x00\x00\x01t\x00\x05agan1q\x00\x00\x03"

// session的創建時間
5) “creationTime”
6) “\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01ouW<K”

//最後的訪問時間
7) “lastAccessedTime”
8) “\xac\xed\x00\x05sr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x01ouW<L”

步驟2:分析SpringSession的redis過期策略

對於過期數據,一般有三種刪除策略:

  1. 定時刪除,即在設置鍵的過期時間的同時,創建一個定時器, 當鍵的過期時間到來時,立即刪除。
  2. 惰性刪除,即在訪問鍵的時候,判斷鍵是否過期,過期則刪除,否則返回該鍵值。
  3. 定期刪除,即每隔一段時間,程序就對數據庫進行一次檢查,刪除裏面的過期鍵。至於要刪除多少過期鍵,以及要檢查多少個數據庫,則由算法決定。
    ​redis 刪除過期數據採用的是懶性刪除+定期刪除組合策略,也就是數據過期了並不會及時被刪除。
    但由於redis是單線程,並且redis對刪除過期的key優先級很低;如果有大量的過期key,就會出現key已經過期但是未刪除。

爲了實現 session 過期的及時性,spring session 採用了定時刪除+惰性刪除的策略。

定時刪除

“spring:session:expirations:1578227700000”

127.0.0.1:6379> type "spring:session:expirations:1578228240000"
set
127.0.0.1:6379> smembers "spring:session:expirations:1578228240000"
1) "\xac\xed\x00\x05t\x00,expires:5eddb9a3-5b1e-4bdd-a289-394b6d42388e"

springsession 定時(1分鐘)輪詢,刪除spring:session:expirations:[?] 的過期members
例如:spring:session:expirations:1578228240000 的1578228240000=2020-01-05 20:44:00:000 即在2020-01-05 20:44:00:000過期。
springsesion 定時檢測超過2020-01-05 20:44:00:000 就刪除spring:session:expirations:1578228240000的members的值
sessionId=5eddb9a3-5b1e-4bdd-a289-394b6d42388e
即刪除

1) "spring:session:expirations:1578228240000"
2) "spring:session:sessions:5eddb9a3-5b1e-4bdd-a289-394b6d42388e"
3) "spring:session:sessions:expires:5eddb9a3-5b1e-4bdd-a289-394b6d42388e"
惰性刪除

spring:session:sessions:expires:5eddb9a3-5b1e-4bdd-a289-394b6d42388e

127.0.0.1:6379> type spring:session:sessions:expires:5eddb9a3-5b1e-4bdd-a289-394b6d42388e
string
127.0.0.1:6379> get spring:session:sessions:expires:5eddb9a3-5b1e-4bdd-a289-394b6d42388e
""
127.0.0.1:6379> ttl spring:session:sessions:expires:5eddb9a3-5b1e-4bdd-a289-394b6d42388e
(integer) 4719

訪問 spring:session:sessions:expires:5eddb9a3-5b1e-4bdd-a289-394b6d42388e的時候,判斷key是否過期,過期則刪除,否則返回改進的值。
例如 訪問spring:session:sessions:expires:5eddb9a3-5b1e-4bdd-a289-394b6d42388e的時候
判斷 ttl spring:session:sessions:expires:5eddb9a3-5b1e-4bdd-a289-394b6d42388e是否過期,過期就直接刪除

1) "spring:session:expirations:1578228240000"
2) "spring:session:sessions:5eddb9a3-5b1e-4bdd-a289-394b6d42388e"
3) "spring:session:sessions:expires:5eddb9a3-5b1e-4bdd-a289-394b6d42388e"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章