Redis【有与无】【Lettuce】L10.编解码器

本文章基于Redis 6.0.9版本,Lettuce 6.0.1.RELEASE版本

目录

1.编解码器

1.1.为什么用ByteBuffer 而不是byte[]

1.2.编解码器中的多样性

1.3.多线程

1.4.压缩

例子1.压缩编解码器的用法

1.5.例子

例子2. BitString编解码器

例子3. JDK序列化器


1.编解码器

编解码器是一种可插入的机制,用于在应用程序和Redis之间对键和值进行代码转换。默认编解码器支持UTF-8编码的字符串键和值。

每个连接都可以将其编解码器传递给扩展的RedisClient.connect方法:

StatefulRedisConnection<K, V> connect(RedisCodec<K, V> codec)
StatefulRedisPubSubConnection<K, V> connectPubSub(RedisCodec<K, V> codec)

Lettuce带有预定义的编解码器:

  • io.lettuce.core.codec.ByteArrayCodec - 使用byte[]作为键和值
  • io.lettuce.core.codec.StringCodec - 使用字符串作为键和值。 使用默认字符集或指定的Charset,并改进了对US_ASCIIUTF-8的支持。
  • io.lettuce.core.codec.CipherCodec - 用于值的透明加密。
  • io.lettuce.core.codec.CompressionCodec - 将GZIPDEFLATE压缩应用于值。

Publish/Subscribe连接使用通道名称和键模式; 消息被视为值。

键和值可以彼此独立地编码,这意味着键可以是java.lang.String,而值是byte[]。 许多其他星座也是可能的,例如:

  • 如果你的数据映射到特定的Java类型,则将数据表示为JSON。 由于编解码器适用于所有操作,因此很难映射不同的类型。
  • 使用Java序列化器(ObjectInputStream/ObjectOutputStream)序列化数据。 允许类型安全的转换,但与其他语言的互操作性较低

  • 使用Kryo序列化数据,以改善类型安全的序列化。
  • 任何专门的编解码器,例如BitStringCodec(请参见下文)

1.1.为什么用ByteBuffer 而不是byte[]

RedisCodec接口接受并返回ByteBuffer以进行数据交换。 ByteBuffer不考虑基础字节的来源。 Lettuce 3.x的byte[]接口要求用户为数组提供准确的数据以进行交换。 因此,如果你有一个只想使用一个子集的数组,则需要创建一个字节数组的新实例并复制数据。 如果你使用其他字节源(例如netty的ByteBuffer或NIO ByteBuffer),则同样适用。 用于解码的ByteBuffer是指向基础数据的指针。 用于编码数据的ByteBuffer可以是纯指针或已分配的内存。 生菜不会释放任何内存(例如池缓冲)。

1.2.编解码器中的多样性

就像在技术的其他每个领域一样,在编解码器方面也没有一个万能的解决方案。 Redis数据结构提供了多种方式。编解码器的关键和价值限制是有意的,在便利性和简单性之间取得了平衡。 Redis API在编码和解码特定数据元素时允许更多差异。 一个很好的例子是Redis哈希。 哈希由其键标识,但存储另一个key/value对。 可以使用与哈希键不同的方法来对键值对的键进行编码。 另一种不同的方法可能是在列表和集合之间使用不同的编码。 使用基本编解码器(例如UTF-8或字节数组)并在基本编解码器之上执行自己的转换通常是更好的主意。

1.3.多线程

编解码器中的一个关键点是编解码器是共享资源,可以被多个线程使用。 你的编解码器需要是线程安全的(无共享,共享或同步)。 每个逻辑Lettuce连接都使用其编解码器实例。 一旦有多个线程发出命令或使用Redis Cluster,便会共享编解码器实例。

1.4.压缩

在Redis中存储更大的数据块时,压缩可能是一个好主意。 任何文本数据结构(例如JSON或XML)都适合压缩。 压缩是在编解码器级别处理的,这意味着你不必更改应用程序即可应用压缩。 CompressionCodec使用GZIP或Deflate压缩为值提供基本和透明的压缩:

例子1.压缩编解码器的用法

StatefulRedisConnection<String, Object> connection = client.connect(
                CompressionCodec.valueCompressor(new SerializedObjectCodec(), CompressionCodec.CompressionType.GZIP)).sync();

StatefulRedisConnection<String, String> connection = client.connect(
                CompressionCodec.valueCompressor(StringCodec.UTF8, CompressionCodec.CompressionType.DEFLATE)).sync();

压缩可以与任何编解码器一起使用,压缩器仅包装内部RedisCodec并压缩/解压缩(compresses/decompresses)交换的数据。 你可以使用提供自己的编解码器的相同方式来构建自己的压缩器。

1.5.例子

例子2. BitString编解码器

public class BitStringCodec extends StringCodec {
    @Override
    public String decodeValue(ByteBuffer bytes) {
        StringBuilder bits = new StringBuilder(bytes.remaining() * 8);
        while (bytes.remaining() > 0) {
            byte b = bytes.get();
            for (int i = 0; i < 8; i++) {
                bits.append(Integer.valueOf(b >>> i & 1));
            }
        }
        return bits.toString();
    }
}

StatefulRedisConnection<String, String> connection = client.connect(new BitStringCodec());
RedisCommands<String, String> redis = connection.sync();

redis.setbit(key, 0, 1);
redis.setbit(key, 1, 1);
redis.setbit(key, 2, 0);
redis.setbit(key, 3, 0);
redis.setbit(key, 4, 0);
redis.setbit(key, 5, 1);

redis.get(key) == "00100011"

例子3. JDK序列化器

public class SerializedObjectCodec implements RedisCodec<String, Object> {
    private Charset charset = Charset.forName("UTF-8");

    @Override
    public String decodeKey(ByteBuffer bytes) {
        return charset.decode(bytes).toString();
    }

    @Override
    public Object decodeValue(ByteBuffer bytes) {
        try {
            byte[] array = new byte[bytes.remaining()];
            bytes.get(array);
            ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(array));
            return is.readObject();
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public ByteBuffer encodeKey(String key) {
        return charset.encode(key);
    }

    @Override
    public ByteBuffer encodeValue(Object value) {
        try {
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            ObjectOutputStream os = new ObjectOutputStream(bytes);
            os.writeObject(value);
            return ByteBuffer.wrap(bytes.toByteArray());
        } catch (IOException e) {
            return null;
        }
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

琴 韵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值