Apache GeodeのExpireについて

### はじめに
Geodeをキャッシュサーバーとして利用した場合、キャッシュデータをいかに消していくか、鮮度を保つかという問題になるとおもいます。
今回はどのようにデータを消していくかについて書いていきます。
### LRU設定を利用する
一番簡単な方法は、Regionを作成する段階でLRU仕様にしてしまうことです。

```
gfsh>create region --name=lruregion --type=PARTITION_HEAP_LRU
```
Regionのショートカットを利用した場合は、デフォルトでlru-heap-percentageが設定されます。
特に追加設定をしていない場合は、ヒープの割合が80%を超えるとデータの退避が始まります。割合を変更したい場合は、server起動時に指定することになります。

```
gfsh>start server --name=server1 --locators=xxx01 --eviction-heap-percentage=９0
```
また、cash.xmlを利用する場合は、resource-managerで設定することができます。
### LRUの検証
実際に試してみましょう。

```
gfsh>put --key="key1" --value="value1" --region=lruregion
 
gfsh>get --key="key1" --region=lruregion
Result      : true
Key Class   : java.lang.String
Key         : key1
Value Class : java.lang.String
Value       : value1
```
データを１件投入した段階では下記のようになっています。

```
gfsh>show metrics --member=xxx02.yahoo.co.jp --categories=member,region
 
Member Metrics
 
Category |            Metric            | Value
-------- | ---------------------------- | -----------
member   | upTime                       | 1686
         | cpuUsage                     | 2
         | currentHeapSize              | 72
         | maximumHeapSize              | 494
region   | totalRegionCount             | 8
         | listOfRegions                | lruregion
         | rootRegions                  | /lruregion
         | totalRegionEntryCount        | 1
         | totalBucketCount             | 1
         | totalPrimaryBucketCount      | 1
```
データを連続して投入していきます。プログラムは割愛します。
あふれる寸前まで来ました。

```
gfsh>show metrics --member=xxx02.yahoo.co.jp --categories=member
 
Member Metrics
 
Category |            Metric            | Value
-------- | ---------------------------- | -----------
member   | upTime                       | 2006
         | cpuUsage                     | 16
         | currentHeapSize              | 394
         | maximumHeapSize              | 494
```
その後続けるとLRUが働き初期に投入したデータが消えたことを確認できました。

```
gfsh>get --key="key1" --region=lruregion
Result      : false
Key Class   : java.lang.String
Key         : key1
Value Class : java.lang.String
Value       : <NULL>

gfsh>show metrics --member=xxx02.yahoo.co.jp --categories=member

Member Metrics
 
Category |            Metric            | Value
-------- | ---------------------------- | -----------
member   | upTime                       | 2884
         | cpuUsage                     | 1
         | currentHeapSize              | 131
         | maximumHeapSize              | 494
```

気になる点としては、かなりメモリが開放され、同時期に投入したデータがすべて消えてしまいました。これは、テストデータの投入時期がほぼ同じことによるものなのか、仕様なのかまでは検証できていません。
### 有効期限の設定
キャッシュデータの鮮度を高めるために、有効期限を設けたくなることがあります。
その場合は、Region毎にexpirationを設定することができます。
#### key毎に一定期間で有効期限を設定
key毎に一定時間で有効期限を設定する場合は`entry-time-to-live-expiration`を利用します。設定の単位は秒となります。`enable-statistics=true`はexpirationを利用するうえでは必須です。

```
gfsh>create region --name=ettlregion --entry-time-to-live-expiration=30 --enable-statistics=true --type=REPLICATE
```

```
gfsh>put --key=key1 --value=value1 --region=ettlregion
Result      : true
Key Class   : java.lang.String
Key         : key1
Value Class : java.lang.String
Old Value   : <NULL>

#15秒後にput
gfsh>put --key=key2 --value=value2 --region=ettlregion
Result      : true
Key Class   : java.lang.String
Key         : key2
Value Class : java.lang.String
Old Value   : <NULL>

#key1をputしてから３０秒後get　消えている
gfsh>get --key=key1  --region=ettlregion
Result      : false
Key Class   : java.lang.String
Key         : key1
Value Class : java.lang.String
Value       : <NULL>

#同じくkey1をputしてから30秒後　key2は残っている
gfsh>get --key=key2  --region=ettlregion
Result      : true
Key Class   : java.lang.String
Key         : key2
Value Class : java.lang.String
Value       : value2
```
putしてからの時間で有効期限を迎えたことがわかります

#### keyの最終アクセスからの期間で有効期限を設定
利用頻度の高いデータは有効期限を伸ばしたいケースでは、`entry-idle-time-expiration`を使用します。

```
gfsh>create region --name=eitregion --entry-idle-time-expiration=30 --enable-statistics=true --type=REPLICATE
```
```
gfsh>put --key=key1 --value=value1 --region=eitregion
Result      : true
Key Class   : java.lang.String
Key         : key1
Value Class : java.lang.String
Old Value   : <NULL>

# key1と同時にput
gfsh>put --key=key2 --value=value2 --region=eitregion
Result      : true
Key Class   : java.lang.String
Key         : key2
Value Class : java.lang.String
Old Value   : <NULL>

#putから１５秒後にget
gfsh>get  --key=key1 --region=eitregion
Result      : true
Key Class   : java.lang.String
Key         : key1
Value Class : java.lang.String
Value       : value1

#putから30秒後にget key2は消えている
gfsh>get  --key=key2 --region=eitregion
Result      : false
Key Class   : java.lang.String
Key         : key2
Value Class : java.lang.String
Value       : <NULL>

#putから30秒後にget 15秒前にgetしたkey1は残っている
gfsh>get  --key=key1 --region=eitregion
Result      : true
Key Class   : java.lang.String
Key         : key1
Value Class : java.lang.String
Value       : value1

```

#### Region毎に有効期限を設定を設定する
keyごとではなく、Region単位で設定したい場合は、`egion-idle-time-expiration`と`region-time-to-live-expiration`を使用してください。検証したところどちらを使っても、最後にputした時間を基準に有効期限が対象のregion内のデータにかかります。getしても有効期限は伸びませんでした。

### 有効期限をむかえたデータについて
有効期限をむえた場合のデータがどうなるかは、`expiration-action`を設定で決まります。デフォルトではinvalidateが指定されますが、この場合は無効になるだけで、実際にはデータは残っているようです。
destroyを使用しないとメモリがあかないことは検証で確認しています。
### まとめ
データのライフサイクル方針や、メモリの節約など、有効期限が必要になる場面は色々ありますので有効に使えると良いですね。