便宜有便宜的辦法-小微企業雲上的springboot集羣方案2.1:redis的消息訂閱和session過時機制

一、session在redis裏面的存儲結構2

上一章講spring session存儲到redis的時候,在redis裏面看到每個session存儲都會生成三條記錄,記錄格式以下:html

這就很麻煩了,爲啥不能一一對應,作彼此的天使呢,搞的一對三,很影響風化啊。究竟是道德的淪喪仍是人性的扭曲,讓咱們走進redis,看下具體的數據內容:java

第一個k-v存儲這個Session的id,是一個Set類型的Redis數據結構。這個key中的最後的1570550340000值是一個時間戳,根據這個Session過時時刻滾動至下一分鐘而計算得出。裏面的值是這樣的redis

第二個k-v用來表示Session在Redis中的過時,是個String類型,這個k-v不存儲任何有用數據,只是表示Session過時而設置。這個key在Redis中的過時時間即爲Session的過時時間間隔spring

第三個k-v用來存儲Session的詳細信息,是hash類型,包括Session的建立時間、過時時間間隔、最近的訪問時間、attributes等等。這個k的過時時間爲Session的最大過時時間 + 5分鐘。若是默認的最大過時時間爲30分鐘,則這個k的過時時間爲35分鐘數據庫

說到這裏,會有個靈魂的拷問,就一個session的存儲,爲啥要搞三條記錄?這裏要提一下HttpSession的接口規範了。緩存

session雖然也是一條數據,可是和普通的數據仍是有不一樣的,咱們去查httpsession的javadoc能夠看到,session的添加和移除都是能夠觸發事件的。session

觸發的前提是對象實現了HttpSessionBindingListener接口,而後咱們再看下HttpSessionBindingListener的部分數據結構

裏面經過HttpSessionBindingEvent來通知session的attribute變化app

這一套下來是否是很熟悉,這就是一個典型的監聽器模型,也是消息機制的主要表現方式,在spring session經過redis實現分佈式的session時,就是經過redis的消息機制來實現標準的session變更通知的,在瞭解具體的作法先,讓咱們先看下redis的消息通知功能。分佈式

二、啥!redis支持消息的發佈訂閱?

Redis從2.8.0版本後,推出 Keyspace Notifications 特性。Keyspace Notifications 容許客戶端能夠以 訂閱/發佈(Sub/Pub)模式,接收那些對數據庫中的鍵和值有影響的操做事件。這些操做事件具體來講,就是 del , expire , set , rpop等啦。

redis默認不會開啓keyspace notifications,由於開啓後會對cpu有消耗,因此開啓須要額外配置redis.conf文件

############################# EVENT NOTIFICATION ##############################

# Redis can notify Pub/Sub clients about events happening in the key space.
# This feature is documented at http://redis.io/topics/notifications
#
# For instance if keyspace events notification is enabled, and a client
# performs a DEL operation on key "foo" stored in the Database 0, two
# messages will be published via Pub/Sub:
#
# PUBLISH __keyspace@0__:foo del
# PUBLISH __keyevent@0__:del foo
#
# It is possible to select the events that Redis will notify among a set
# of classes. Every class is identified by a single character:
#
#  K     Keyspace events, published with __keyspace@<db>__ prefix.
#  E     Keyevent events, published with __keyevent@<db>__ prefix.
#  g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
#  $     String commands
#  l     List commands
#  s     Set commands
#  h     Hash commands
#  z     Sorted set commands
#  x     Expired events (events generated every time a key expires)
#  e     Evicted events (events generated when a key is evicted for maxmemory)
#  A     Alias for g$lshzxe, so that the "AKE" string means all the events.
#
#  The "notify-keyspace-events" takes as argument a string that is composed
#  of zero or multiple characters. The empty string means that notifications
#  are disabled.
#
#  Example: to enable list and generic events, from the point of view of the
#           event name, use:
#
#  notify-keyspace-events Elg
#
#  Example 2: to get the stream of the expired keys subscribing to channel
#             name __keyevent@0__:expired use:
#
#  notify-keyspace-events Ex
#
#  By default all notifications are disabled because most users don't need
#  this feature and the feature has some overhead. Note that if you don't
#  specify at least one of K or E, no events will be delivered.
notify-keyspace-events "Ex"

關鍵就是最下一句,Ex的意思能夠看上面的註釋。啓動後只要咱們訂閱一個特定的channel,該channel下面的數據變化咱們就能收到通知了。

改好配置,重啓redis,就可以開啓消息通知了。

Redis中帶有過時的key有兩種方式:

  • 當訪問時發現其過時
  • Redis後臺逐步查找過時鍵

問題時訪問時發現過時可能會在好久之後,因此怎麼才能在key過時的時候就知道呢?

spring-session中有個定時任務,每一個整分鐘都會查詢相應的spring:session:expirations:整分鐘的時間戳中的過時SessionId,而後再訪問一次這個sessionId,即spring:session:sessions:expires:SessionId,以便可以讓Redis及時的產生key過時事件——即Session過時事件。而這個定時任務的時間時能夠配置的,配置的參數就時上一章結尾說的cleanupCron

public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration
		implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware,
		SchedulingConfigurer {

	static final String DEFAULT_CLEANUP_CRON = "0 * * * * *";

	private String cleanupCron = DEFAULT_CLEANUP_CRON;

默認就是一分鐘清理一次過時的緩存,能夠根據本身的需求作更改。

三、總結

  1. spring session存到redis的每一個session數據會有三條記錄,一條存儲session自身的信息,另外兩條存儲session過時的信息
  2. redis能夠開啓Keyspace Notifications服務,開啓後redis的數據出現變更會有通知消息
  3. spring session能夠配置定時任務掃描存到redis的session數據中關於過時信息的兩條,定時任務的配置在cleanupCron裏面

我這裏其實講的不是很詳細,關於spring session方面的細節,你們能夠看這一系列的文章,講的很好,但看的挺累。

相關文章
相關標籤/搜索