spring framework / boot / data 徹底活用 〜spring data redis 編〜

21
Spring Framework / Boot / Data 徹底活用 August 28, 2015 Spring in Summer ~ 夏なのにSpring Naohiro Yoshida Recruit Technologies Co.,Ltd. ~Spring Data Redis 編~

Upload: naohiro-yoshida

Post on 17-Jan-2017

2.086 views

Category:

Technology


4 download

TRANSCRIPT

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から使ってみる

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~

まとめ■ Spring Data RedisのRedisTemplateによりRedis操作は簡単 ■ Spring Data RedisでのRedis Clusterは直接サポートされていない ■ 実運用に耐えるRedis構成に合わせるとある程度のカスタマイズが必要