4.7. 数据编码


编码是在存储数据前由数据进行的数据转换操作,以及从存储中读取数据时进行的数据转换操作。

4.7.1. 概述

编码允许在 API 调用(map、监听器、流等)期间处理某些数据格式,而有效存储的格式会有所不同。

数据转换由 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 会自动选择 Encoder。下表显示了哪些内部 Encoder 用于以下配置:

模式配置encoder描述

embedded/Server

Default(默认)

IdentityEncoder

passthrough encoder,没有进行转换

embedded

StorageType.OFF_HEAP

GlobalMarshallerEncoder

使用 Data Grid internal marshaller 转换为 byte[].可以委托到缓存管理器中配置的 marshaller。

embedded

StorageType.BINARY

BinaryEncoder

使用 Data Grid internal marshaller 转换为 byte[],但 primitives 和 String 除外。

服务器

StorageType.OFF_HEAP

IdentityEncoder

远程客户端接收的字节[]

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. 定义自定义 Encoders

自定义编码器可以在 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
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.