❶ spring boot + redis 實現session共享分析
HttpSession是由servelet容器進行管理的。而我們常用的應用容器有 Tomcat/Jetty等, 這些容器的HttpSession都是存放在對應的應用容器的內存中,在分布式集群的環境下,通常我們使用Nginx或者LVS、Zuul等進行反向代理和負載均衡,因此用戶請求是由一組提供相同服務的應用來進行處理,而用戶最終請求到的服務由Nginx和LVS、Zuul進行確定。
那麼問題就來了,我們怎樣保證多個相同的應用共享同一份session數據?對於這種問題Spring為我們提供了Spring Session進行管理我們的HttpSession。項目地址: http://projects.spring.io/spring-session/
1.添加Spring session的包,而Spring session 是將HttpSession存放在Redis中,因此需要添加Redis的包。我們這里是用了Spring boot進行配置Rdies。
2.使用@EnableRedisHttpSession註解進行配置啟用使用Spring session。
3.配置我們的Redis鏈接,我們這里使用的是Spring Boot作為基礎進行配置,因此我們只需要在YML或者Properties配置文件添加Redis的配置即可。
4.創建請求的控制器來進行確定我們是否啟用Session 共享。
5.將當前的工程拷貝一份.
通過上面請求顯示的結果我們可以看出使用的是同一個Seesion,我們也可以查看下存在Redis中的Session。我這里使用RDM進行查看,我們還可以查看Session的屬性。從圖可以看出我們存進入的url屬性。
我們從啟動Spring Session的配置註解@EnableRedisHttpSession開始。
1.我們可以通過@EnableRedisHttpSession可以知道,Spring Session是通過RedisHttpSessionConfiguration類進行配置的。
2.我們在RedisHttpSessionConfiguration類種的注釋可以知道,該類是用於創建一個過濾SessionRepositoryFilter。
3.探究下SessionRepositoryFilter類是在哪裡創建創建過程作用。
(1)哪裡創建:
通過搜索RedisHttpSessionConfiguration發現SessionRepositoryFilter的創建不是在RedisHttpSessionConfiguration,而是在父類中創建。
(2)SessionRepositoryFilter創建過程:
這里我們可以總結下:
Redis確保鏈接的情況下。
1.創建sessionRedisTemplate
2.創建
3.創建SessionRepositoryFilter
(3)SessionRepositoryFilter的作用:
SessionRepositoryFilter的主要作用接管Seession的管理。我們可以從下面幾個點知道為什麼?
4.我們研究下是怎樣接管Session?
(1)存儲Session的過程
當調用SessionRepositoryFilter.this.sessionRepository.save(session)完畢後,會判斷當前的SessionId是否與請求的中的Cookie中SessionId一致,若不一致的情況下會調用onNewSession()方法,我們可以通過配置類的可以看到使用的是
CookieHttpSessionStrategy();
從CookieHttpSessionStrategy.onNewSession()方法可以看到是將SessionId寫到Cookie中。
(2)獲取Session的過程
我們根據源碼的分析可以知道:
1.Spring Session 是通過SessionRepositoryFilter過濾器進行攔截,然後通過繼承HttpServletRequestWrapper進行管理Session。
2.Spring Session 為我們提供了3中存放的策略而每種策略提供對應的註解啟動。分別為:
(1)NoSql形式的MongoDb:@EnableMongoHttpSession
(2)持久化形式的JDBC:@EnableJdbcHttpSession
(3)緩存形式的Redis:@EnableRedisHttpSession
3.Spring Session 共享Session過程:
(1)先過程過濾器存儲將SessionID存放到本地的Cookie 和Redis中。
如果本地沒有啟用Cookie的情況下,Spring Session也就不能使用。
(2)獲取Session的時候,先從請求中獲取Session,Session不為空的情況下直接返回Session,若當前的Session為空的情況下,從Cookie中獲取SessionId,判斷SessionId不為空,再從Redis中獲取Session,若從Redis中獲取到的Session不為空將Session存放到請求中,再返回Session,如果從Redis中獲取的Session為空,再創建新的Session並且添加到請求中,後返回Session。
❷ 查詢數據放入了redis中緩存,怎麼查看緩存的數據
普通分頁
一般分頁做緩存都是直接查找出來,按頁放到緩存里,但是這種緩存方式有很多缺點。
如緩存不能及時更新,一旦數據有變化,所有的之前的分頁緩存都失效了。
比如像微博這樣的場景,微博下面現在有一個頂次數的排序。這個用傳統的分頁方式很難應對。
一種思路
最近想到了另一種思路。
數據以ID為key緩存到Redis里;
把數據ID和排序打分存到Redis的skip list,即zset里;
當查找數據時,先從Redis里的skip list取出對應的分頁數據,得到ID列表。
用multi get從redis上一次性把ID列表裡的所有數據都取出來。如果有缺少某些ID的數據,再從資料庫里查找,再一塊返回給用戶,並把查出來的數據按ID緩存到Redis里。
在最後一步,可以有一些小技巧:
比如在缺少一些ID數據的情況下,先直接返回給用戶,然後前端再用ajax請求缺少的ID的數據,再動態刷新。
❸ SpringBoot整合SpringSeesion實現Redis緩存
使用Spring Boot開發項目時我們經常需要存儲Session,因為Session中會存一些用戶信息或者登錄信息。傳統的web服務是將session存儲在內存中的,一旦服務掛了,session也就消失了,這時候我們就需要將session存儲起來,而Redis就是用來緩存seesion的一種非關系型資料庫,我們可以通過配置或者註解的方式將Spring Boot和Redis整合。而在分布式系統中又會涉及到session共享的問題,多個服務同時部署時session需要共享,Spring Session可以幫助我們實現這一功能。將Spring Session集成到Spring Boot框架中並使用Redis進行緩存是目前非常流行的解決方案,接下來就跟著我一起學習吧。
工具/材料
IntelliJ IDEA
首先我們創建一個Spring Boot 2.x的項目,在application.properties配置文件中添加Redis的配置,Spring和Redis的整合可以參考我其他的文章,此處不再詳解。我們設置服務埠server.port為8080埠用於啟動第一個服務。
接下來我們需要在pom文件中添加spring-boot-starter-data-redis和spring-session-data-redis這兩個依賴,spring-boot-starter-data-redis用於整合Spring Boot和Redis,spring-session-data-redis集成了spring-session和spring-data-redis,提供了session與redis的整合方案。
接下來我們創建一個配置類RedisSessionConfig,這個類使用@Configuration註解表明這是一個配置類。在這個類上我們同時添加註解@EnableRedisHttpSession,表示開啟Redis的Session管理。如果需要設置失效時間可以使用@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)表示一小時後失效。若同時需要設置Redis的命名空間則使用@EnableRedisHttpSession(maxInactiveIntervalInSeconds=3600, redisNamespace="{spring.session.redis.namespace}") ,其中{spring.session.redis.namespace}表示從配置文件中讀取這個命名空間。
配置完成後我們寫一個測試類SessionController,在這個類中我們寫兩個方法,一個方法用於往session中存數據,一個用於從session中取數據,代碼如下圖所示,我們存取請求的url。啟動類非常簡單,一般都是通用的,我們創建一個名為SpringbootApplication的啟動類,使用main方法啟動。
接下來我們使用Postman分別請求上面兩個介面,先請求存數據介面,再請求取數據介面,結果如下圖所示,我們可以看到數據已從redis中取出。另外需要注意sessionId的值,這是session共享的關鍵。
為了驗證兩個服務是否共享了session,我們修改項目的配置文件,將服務埠server.port改為8090,然後再啟動服務。此時我們不必在請求存數據的介面,只需要修改請求埠號再一次請求取數據的介面即可。由下圖可以看到兩次請求的sessionId值相同,實現了session的共享。
以上我們完成了SpringBoot整合SpringSeesion實現Redis緩存的功能,在此我們還要推薦一個Redis的可視化工具RedisDesktopManager,我們可以配置Redis資料庫的連接,然後便可以非常直觀地查看到存儲到Redis中的session了,如下圖所示,session的命名空間是share,正是從配置文件中讀取到的。
特別提示
如果Redis伺服器是很多項目共用的,非常建議配置命名空間,否則同時打開多個項目的瀏覽器頁面可能會導致session錯亂的現象。