Spring Framework / Boot / Data 徹底活用 〜Spring Data Redis 編〜
-
Upload
naohiro-yoshida -
Category
Technology
-
view
2.087 -
download
4
Transcript of Spring Framework / Boot / Data 徹底活用 〜Spring Data Redis 編〜
Spring Framework / Boot / Data 徹底活用
August 28, 2015 Spring in Summer ~ 夏なのにSpring !Naohiro Yoshida Recruit Technologies Co.,Ltd.
~Spring Data Redis 編~
自己紹介(def me {:name "吉田 尚弘"
:job "アーキテクト" :lang ["Java" "Clojure" "Scala" "golang"] :spring-‐use {"流通系企業基幹システム"
"高校生向け学習アプリAPIサーバ"})
リクルートにおけるSpringへの取り組み■ リクルートでは全社標準FWとしてSpringの採用を決定 ■ 専門部隊で検証やサイトへの適用を進めている
学んだプラクティスについては随時ブログや勉強会等で公開予定
!!!!!!
API/バックエンド
Spring Boot
Spring Framework
Spring XXX 独自LIB
!フロントエンド
node.js
!!!!!!!!!
API/バックエンド
本日の内容
Spring BootでのSpring Data Redisの使い方とプラクティス
Spring Boot
Spring Framework
Spring Rabbit
Spring Boot Autoconfigure
Spring JMSSpring Boot Actuator
Spring Data Redis
Spring Data Elasticsearch
Spring ・・・
Spring Data Redis■ SpringでRedisを操作するためのライブラリ ■ JedisのローレベルAPIを使うのではなく利用しやすいTemplateを提供している
! @Autowired private RedisTemplate<Object, Object> redisTemplate;! public void access() { // value redisTemplate.opsForValue().set(key, System.currentTimeMillis()); Object value = redisWriterTemplate.opsForValue().get(key); // list redisTemplate.opsForList().rightPush(key, value); value = redisWriterTemplate.opsForList().leftPop(key); // expire Date expireAt = DateUtils.addHours(dateSupplier.get(), 1); redisTemplate.expireAt(key, expireAt);}!
Spring Data Redis ~Cache利用~■ RedisCacheManagerを利用することでspring-contextのCache機構と連携可
@Configuration@EnableCachingpublic class RedisConfiguration extends CachingConfigurerSupport {! @Bean @Autowired public CacheManager cacheManager( RedisTemplate<Object,Object> redisTemplate){ RedisCacheManager manager = new RedisCacheManager(redisTemplate);! //有効期限設定 (not required) Map<String, Long> expires = new HashMap<String, Long>(); expires.put("cache.expire.180", new Long(3 * 60)); manager.setExpires(expires); return manager;
}}
Spring Data Redis ~Cache利用~
// RedisCacheManagerで指定したexpiresのkeyをvalue属性に // 指定することにより有効期限が設定される、expiresにないvalue属性の場合は無期限 @Override @Cacheable(value = "cache.expire.180", key = "'cache.master.seatTypes'") public List<CodeAndName> selectSeatTypes() { return selectList("sqlfilename"); }! // この場合redisでのkeyは //「cache.master.selectRailroad/ + 引数のrailroadCode値」 @Cacheable(value = "cache.permanent.selectRailroad", key = "'cache.master.selectRailroad/' + #railroadCode") public CodeAndName selectRailroad(String railroadCode) { return selectOne("sqlfilename", railroadCode); }
■ キャッシュとして戻り値を保持したいメソッドにCachableアノテーションを定義 ■ Redisに存在しない場合のみメソッドの中身が呼び出される ■ 下のコードはSQL実行結果をキャッシュとしてRedisに乗せる例
Spring Boot Application
Spring Bootで利用するには■ spring-boot-starter-redisとspring-boot-autoconfigureを依存関係に追加するだけ ■ RedisAutoConfigurationがRedisTemplate作成する ■ とりあえず使ってみるのは非常に簡単
Jedis
RedisTemplate
アプリケーションコード
Redis Properties
RedisAuto Configuration
Redis
spring: data: redis: host: localhost port: 6379 pool: max-active:20
application.yml
Redisの構成の選択肢 ~Redis Cluster~■ 擬似的なMulti Master構成、最低3台のMaster Nodeが必要 ■ データがシャーディングされNode毎に別のデータを保持 ■ 可用性をちゃんと考慮すると6台のNodeが必要
Node1 !① ⑦ ⑨
Node2 !② ③ ⑥
Node 3 !④ ⑤ ⑧
それぞれ管理しているhash slotを教え合っている
Node1 Slave
Node2 Slave
Node3 Slave
Client
1.CLUSTER HINTS 2.hash slotと
nodeの対応
3.対象ノードからGET
Node 1 Node 2 Node 3
Redisの構成の選択肢 ~Redis Sentinel~■ Master判定専用のプロセス(sentinel)を用いたMaster/Slave構成 ■ 複数のsentinelによる投票によりMasterが決定される(複数クラスタ管理可) ■ 多数決によるMaster障害検知なので3台は必要
Redis Master
Redis Slave #1
Redis Slave #2
Sentinel1 sentinel2 sentinel3
Client
1.Master 問い合わせ
2.Master Node の場所返却
3.データSET
Redisの構成の選択肢 ~Load Balancer~
!Load Balancer
VIP1 VIP 2
Redis Master
Redis Slave #2
Redis Slave #1
■ LBにWrite用のVIPとRead用のVIPを用意 ■ クライアントからはVIPにアクセスしノードダウン/Master昇格を意識しない ■ Master 1台 / Slave 1台でも構成可能
Client
SET GET
Sentinel1 sentinel2 sentinel3
Master障害検知と昇格の1手段としてバックエンドで sentinelを利用する
Spring + Redis Cluster■ Jedis 2.7.2からRedis Clusterにも安定版のRedis 3.0.Xに対応している ■ しかし現在Spring Data RedisはRedis Clusterに対応していない
Spring Boot Application
Spring + Redis Sentinel
RedisTemplate
Jedis Sentinel Pool
JedisConnectionFactory
Jedis Pool
sentinel1 sentinel2
sentinel3
Redis Master
■ JedisSentinelPoolがsentinelプロセスからMasterのHostAndPort取得 ■ MasterのHost And Portを取得してMasterに接続
全sentinelから定期的に Maserの情報を取得
Maserに対してアクセス
Spring Boot Application
Spring + Redis Sentinel ~Master 判定~
JedisSentinelPool
JedisConnectionFactory
■ 起動時にSentinelに対する専用のListenerを生成してMasterのAddrを取得 ■ SentinelからのMaster変更を検知する毎にメモリ内のMasterのAddrを変更 ■ 起動時に最低1つのsentinelにアクセスできる必要がある
Master Listener
Master Listener
Sentinel1 Sentinel2 Sentinel3
Master Listener
Sentinelに対してsubscribe処理Master情報を受け取る
Sentinel数分のMasterListenerをそれぞれ別スレッドで起動。
最初にget-master-addr-by-nameでsentinelから直接masterのHost/Portを取得。ここで取得できないと無限ループ
Spring Boot Applicaton起動時
■ Master判定された後はsentinelから切断された場合でも暫定的に利用可 ■ Masterが切り替わった時にはWriteが失敗する ■ sentinel復旧後は自動的に再接続
Spring + Redis Sentinel ~Sentinel停止~
Spring Boot Application
Redis Template
JedisSentinelPool
JedisConnectionFactory
JedisPool
Redis Master
MasterListenerが デフォルトで5秒に一回接続試行
Master Listener
Master Listener
Master Listener
Sentinel1 Sentinel2 Sentinel3
×× ×
Spring Boot Application
RedisTemplate
JedisConnectionFactory
JedisPool
Redis Master
■ Slave用のJedisConnectionFactoryを用意する必要がある。 ■ Slaveが複数になった場合の分散や生死状態の判定は別途仕組みが必要。
JedisConnection
JedisPool
Redis Slave
Spring + Redis Sentinel ~Slaveへのアクセス~
Jedis Sentinel Pool
sentinel1 sentinel2
sentinel3
ReadかWriteかによって利用するConnectionFactoryを切り替える
Spring Boot Application
Spring + VIP
JedisConnectionFactory
JedisPool
Redis Master
Redis Slave #1
Redis Slave #2
Load BalancerVIP1 VIP 2
RedisTemplate
JedisConnectionFactory
JedisPool
■ 死活監視やアクセス分散をLBに委譲する ■ 読取用と書込用のJedisConnectionFactoryはそれぞれ必要
キャッシュ用クラスタ
■ 複数Master/Slaveのクラスタ構成もRepository層以上からは透過 ■ 将来的なRedis Clusterへの移行時の影響を低減 ■ 標準では対応していないので拡張が必要 -> 現在RTCで開発中
Spring Boot Application
Master Slave #1 Slave #2
RedisTemplate
JedisConnection Factory
JedisConnection Factory
JedisConnection Factory
JedisConnection Factory
Load BalancerVIP1 VIP 2 VIP 3 VIP 4
Master Slave #1 Slave #2
一時データ用クラスタ
・キーのprefixなどでクラスタ判定 ・発行コマンドでWrite/Read判定
Spring + VIP ~Multiple JedisConnectionFactory~