読者です 読者をやめる 読者になる 読者になる

Commons JCS のキャッシュ保持期間

Apache Commons JCS のキャッシュを保持する期間設定には以下のようなものがあります。

  • MaxLifeSeconds
  • MaxMemoryIdleTimeSeconds

MaxLifeSeconds で一定時間が経つと無効になるキャッシュを設定でき、MaxMemoryIdleTimeSeconds で一定時間参照されないと削除されるキャッシュを設定できます。


今回はこれらの設定を試す簡単なサンプルを Groovy で作成してみました。

ソースは http://github.com/fits/try_samples/tree/master/blog/20120407/

MaxLifeSeconds(一定時間で無効になるキャッシュ設定)

まずは MaxLifeSeconds を使って一定時間経過すると無効になるキャッシュを試してみます。

JCS のキャッシュ設定ファイル cache.ccf を以下のように設定しました。(キャッシュは 3秒間だけ保持)
cache.ccf はクラスパスの通った場所に配置します。*1

なお、MaxLifeSeconds を有効化するには IsEternal を false にする必要があります。

cache.ccf(キャッシュ設定)
jcs.region.sample1=
jcs.region.sample1.elementattributes.IsEternal=false
jcs.region.sample1.elementattributes.MaxLifeSeconds=3

スクリプトは以下の通りです。

jcs_sample1.groovy
@Grapes([
    @Grab('org.apache.jcs:jcs:1.3'),
    @GrabExclude('logkit#logkit'),
    @GrabExclude('avalon-framework#avalon-framework')
])
import org.apache.jcs.JCS

//一定時間で無効になるキャッシュ
def jcs = JCS.getInstance('sample1')

jcs.put('data1', 'cached_data')

Thread.sleep(2000)

println "2秒後: ${jcs.get('data1')}"

Thread.sleep(2000)

println "さらに2秒後: ${jcs.get('data1')}"

実行結果は以下の通り。
4秒後にキャッシュが無くなっています。

実行例
> groovy jcs_sample1.groovy
4 07, 2012 7:30:00 午後 org.apache.jcs.engine.control.CompositeCacheManager configure
情報: Creating cache manager from config file: /cache.ccf
・・・
情報: initialized LRUMemoryCache for sample1
・・・
2秒後: cached_data
さらに2秒後: null

MaxMemoryIdleTimeSeconds(一定時間参照されないと削除されるキャッシュ設定)

次に、MaxMemoryIdleTimeSeconds で一定時間参照されないと削除されるキャッシュを試してみます。

MaxMemoryIdleTimeSeconds を有効化するには UseMemoryShrinker を true に設定します。
こうする事で MemoryShrinker*2 が ShrinkerIntervalSeconds の間隔でバックグラウンド実行されて、最後に参照されてから MaxMemoryIdleTimeSeconds より経過したキャッシュを削除します。*3

cache.ccf(キャッシュ設定)
jcs.region.sample2=
jcs.region.sample2.cacheattributes.UseMemoryShrinker=true
jcs.region.sample2.cacheattributes.MaxMemoryIdleTimeSeconds=4
jcs.region.sample2.cacheattributes.ShrinkerIntervalSeconds=3
jcs_sample2.groovy
・・・
//一定時間参照されないと削除されるキャッシュ
def jcs = JCS.getInstance('sample2')

jcs.put("data1", "cached_data1")
jcs.put("data2", "cached_data2")

println "data1 = ${jcs.get('data1')}, data2 = ${jcs.get('data2')}"

Thread.sleep(2000)

println "2秒後: data1 = ${jcs.get('data1')}"

Thread.sleep(4500)

println "さらに4.5秒後: data1 = ${jcs.get('data1')}, data2 = ${jcs.get('data2')}"

実行結果は以下の通り。
data2 は 6秒後に実行される 2回目の MemoryShirinker に削除されますが、data1 は一度参照されたため、この時点では削除されません。

MaxMemoryIdleTimeSeconds の場合、MemoryShirinker に削除されない限りキャッシュは保持されるため、MaxMemoryIdleTimeSeconds を越えた 4.5秒が経っていても data1 のキャッシュは健在です。

実行例
> groovy jcs_sample2.groovy
・・・
data1 = cached_data1, data2 = cached_data2
2秒後: data1 = cached_data1
さらに4.5秒後: data1 = cached_data1, data2 = null

MaxLifeSeconds + MaxMemoryIdleTimeSeconds

最後に MaxLifeSeconds と MaxMemoryIdleTimeSeconds を組み合わせて設定してみました。

cache.ccf(キャッシュ設定)
jcs.region.sample3=
jcs.region.sample3.elementattributes.IsEternal=false
jcs.region.sample3.elementattributes.MaxLifeSeconds=8
jcs.region.sample3.cacheattributes.UseMemoryShrinker=true
jcs.region.sample3.cacheattributes.MaxMemoryIdleTimeSeconds=4
jcs.region.sample3.cacheattributes.ShrinkerIntervalSeconds=3
jcs_sample3.groovy
・・・
def jcs = JCS.getInstance('sample3')

jcs.put("data1", "cached_data1")

Thread.sleep(3000)

println "3秒後: data1 = ${jcs.get('data1')}"

Thread.sleep(3000)

println "さらに3秒後: data1 = ${jcs.get('data1')}"

Thread.sleep(3500)

println "さらに3.5秒後: data1 = ${jcs.get('data1')}"

実行結果は以下の通り。
MaxMemoryIdleTimeSeconds 内の間隔でキャッシュが参照されていても、MaxLifeSeconds より経過するとキャッシュが無効化されています。

実行例
> groovy jcs_sample3.groovy
・・・
3秒後: data1 = cached_data1
さらに3秒後: data1 = cached_data1
・・・ org.apache.jcs.engine.memory.shrinking.ShrinkerThread checkForRemoval
情報: Exceeded maxLifeSeconds: data1
さらに3.5秒後: data1 = null

*1:Web アプリケーションの場合は WEB-INF/classes に配置します

*2:実際は org.apache.jcs.engine.memory.shrinking.ShrinkerThread クラス

*3:ShrinkerThread クラスの shrink メソッド内で lastAccessTime + maxMemoryIdleTime < now が成り立った際にキャッシュを削除している