4.7. データエンコーディング
エンコーディングは、データを保存する前、およびストレージから読み戻すときに、Data Grid キャッシュによって実行されるデータ変換操作です。
4.7.1. 概要
エンコーディングを使用すると、API 呼び出し中に特定のデータ形式 (マップ、リスナー、ストリームなど) を処理できますが、効果的に保存される形式は異なります。
データ変換は、org.infinispan.commons.dataconversion.Encoder のインスタンスによって処理されます。
public interface Encoder { /** * Convert data in the read/write format to the storage format. * * @param content data to be converted, never null. * @return Object in the storage format. */ Object toStorage(Object content); /** * Convert from storage format to the read/write format. * * @param content data as stored in the cache, never null. * @return data in the read/write format */ Object fromStorage(Object content); /** * Returns the {@link MediaType} produced by this encoder or null if the storage format is not known. */ MediaType getStorageFormat(); }
4.7.2. デフォルトのエンコーダー
Data Grid は、キャッシュ設定に応じてエンコーダーを自動的に選択します。以下の表は、複数の設定に使用される内部エンコーダーを示しています。
モード | 設定 | エンコーダー | 説明 |
---|---|---|---|
組み込み/サーバー | デフォルト | IdentityEncoder | パススルーエンコーダ、変換なし |
組み込み | StorageType.OFF_HEAP | GlobalMarshallerEncoder | Data Grid の内部マーシャラーを使用して byte[] に変換します。キャッシュマネージャーで設定されたマーシャラーに委譲できます。 |
組み込み | StorageType.BINARY | BinaryEncoder | Data Grid の内部マーシャラーを使用して、プリミティブおよび String を除いて byte[] に変換します。 |
サーバー | StorageType.OFF_HEAP | IdentityEncoder | リモートクライアントが受信したように byte[] を直接保存 |
4.7.3. プログラムでの上書き
AdvancedCache から .withEncoding() メソッドバリアントを呼び出すことで、キーと値の両方に使用されるエンコーディングをプログラムで上書きできます。
たとえば、OFF_HEAP として設定された以下のキャッシュについて考えてみましょう。
// Read and write POJO, storage will be byte[] since for // OFF_HEAP the GlobalMarshallerEncoder is used internally: cache.put(1, new Pojo()) Pojo value = cache.get(1) // Get the content in its stored format by overriding // the internal encoder with a no-op encoder (IdentityEncoder) Cache<?,?> rawContent = cache.getAdvancedCache().withEncoding(IdentityEncoder.class); byte[] marshalled = (byte[]) rawContent.get(1);
オーバーライドは、エントリー数のカウントや OFF_HEAP キャッシュの byte [] のサイズの計算など、キャッシュ内の操作にデコードが不要な場合に役立ちます。
4.7.4. カスタムエンコーダーの定義
カスタムエンコーダーは EncoderRegistry に登録できます。
キャッシュを起動する前に、クラスターの各ノードで登録が行われていることを確認してください。
gzip で圧縮/解凍するために使用されるカスタムエンコーダを考えてみましょう。
public class GzipEncoder implements Encoder { @Override public Object toStorage(Object content) { assert content instanceof String; return compress(content.toString()); } @Override public Object fromStorage(Object content) { assert content instanceof byte[]; return decompress((byte[]) content); } private byte[] compress(String str) { try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); GZIPOutputStream gis = new GZIPOutputStream(baos)) { gis.write(str.getBytes("UTF-8")); gis.close(); return baos.toByteArray(); } catch (IOException e) { throw new RuntimeException("Unabled to compress", e); } } private String decompress(byte[] compressed) { try (GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(compressed)); BufferedReader bf = new BufferedReader(new InputStreamReader(gis, "UTF-8"))) { StringBuilder result = new StringBuilder(); String line; while ((line = bf.readLine()) != null) { result.append(line); } return result.toString(); } catch (IOException e) { throw new RuntimeException("Unable to decompress", e); } } @Override public MediaType getStorageFormat() { return MediaType.parse("application/gzip"); } @Override public boolean isStorageFormatFilterable() { return false; } @Override public short id() { return 10000; } }
以下で登録できます。
GlobalComponentRegistry registry = cacheManager.getGlobalComponentRegistry(); EncoderRegistry encoderRegistry = registry.getComponent(EncoderRegistry.class); encoderRegistry.registerEncoder(new GzipEncoder());
次に、キャッシュからのデータの読み書きに使用します。
AdvancedCache<String, String> cache = ... // Decorate cache with the newly registered encoder, without encoding keys (IdentityEncoder) // but compressing values AdvancedCache<String, String> compressingCache = (AdvancedCache<String, String>) cache.withEncoding(IdentityEncoder.class, GzipEncoder.class); // All values will be stored compressed... compressingCache.put("297931749", "0412c789a37f5086f743255cfa693dd5"); // ... but API calls deals with String String stringValue = compressingCache.get("297931749"); // Bypassing the value encoder to obtain the value as it is stored Object value = compressingCache.withEncoding(IdentityEncoder.class).get("297931749"); // value is a byte[] which is the compressed value