内存库-ignite之序列化自定义

ignite序列化自定义



前言

ignite是一款分布式存算一体库,跟redis一样它也是基于内存运行的,所以性能表现极佳,而且相比于redis而言,它除了kv形式还可以使用表和sql,操作更为便捷。


一、为什么要自定义ignite的序列化逻辑?

在日前的工作中,使用ignite存算一体库时,由于我们的实体属性字段用了枚举类型,导致报错,排查后发现是序列化问题,改动实体属性类型工作量较大,所以选择自定义ignite序列化逻辑

二、实现步骤

1.定义序列化器

代码如下(示例):

// IgniteSerializer

//实现ignite的BinarySerializer接口
public class IgniteSerializer implements BinarySerializer {
    private static final Map<String, TriConsumer<BinaryWriter, String, Object>> WRITER_MAP = new ConcurrentHashMap<>();

    static {
        WRITER_MAP.put("BigDecimal", (writer, fieldName, value) -> writer.writeDecimal(fieldName, (BigDecimal) value));
        WRITER_MAP.put("Boolean", (writer, fieldName, value) -> writer.writeInt(fieldName, (boolean) value ? 1 : 0));
        WRITER_MAP.put("Byte", (writer, fieldName, value) -> writer.writeByte(fieldName, (byte) value));
        WRITER_MAP.put("Character", (writer, fieldName, value) -> writer.writeChar(fieldName, (char) value));
        WRITER_MAP.put("Date", (writer, fieldName, value) -> writer.writeDate(fieldName, (Date) value));
        WRITER_MAP.put("Double", (writer, fieldName, value) -> writer.writeDouble(fieldName, (double) value));
        WRITER_MAP.put("Float", (writer, fieldName, value) -> writer.writeFloat(fieldName, (float) value));
        WRITER_MAP.put("Enum", (writer, fieldName, value) -> writer.writeInt(fieldName, ((MapEnum) value).getKey()));
        WRITER_MAP.put("Integer", (writer, fieldName, value) -> writer.writeInt(fieldName, (int) value));
        WRITER_MAP.put("Long", (writer, fieldName, value) -> writer.writeLong(fieldName, (long) value));
        WRITER_MAP.put("Short", (writer, fieldName, value) -> writer.writeShort(fieldName, (short) value));
        WRITER_MAP.put("String", (writer, fieldName, value) -> writer.writeString(fieldName, (String) value));
        WRITER_MAP.put("Time", (writer, fieldName, value) -> writer.writeTime(fieldName, (Time) value));
        WRITER_MAP.put("Timestamp", (writer, fieldName, value) -> writer.writeTimestamp(fieldName, (Timestamp) value));
    }
	
	// 处理写逻辑
    @Override
    public void writeBinary(Object obj, BinaryWriter writer) throws BinaryObjectException {
        var declaredFields = obj.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            String fieldName = field.getName();
            var fieldType = field.getType();
            try {
                var fieldVal = field.get(obj);

                if (fieldVal != null) {
                    var writerMethod = WRITER_MAP.get(fieldType.getSimpleName());
                    if (writerMethod != null) {
                        writerMethod.accept(writer, fieldName, fieldVal);
                    }
                }
            } catch (IllegalAccessException e) {
                throw new BinaryObjectException("Failed to write field: " + fieldName + " of type: " + fieldType, e);
            }
        }
    }

	// 处理读逻辑
    @Override
    public void readBinary(Object obj, BinaryReader reader) throws BinaryObjectException {
        Set<Field> declaredFields = Arrays.stream(obj.getClass().getDeclaredFields()).collect(Collectors.toSet());
        if (obj.getClass().getSuperclass() != null) {
            declaredFields.addAll(
                    Arrays.stream(obj.getClass().getSuperclass().getDeclaredFields()).collect(Collectors.toSet()));
        }
        for (Field field : declaredFields) {
            try {
                field.setAccessible(true);
                var fieldVal = reader.readObject(field.getName());

                if (fieldVal == null) {
                    continue;
                }

                if (field.getType().isEnum()) {
                    Enum[] enumConstants = (Enum[]) field.getType().getEnumConstants();
                    for (Enum enumConstant : enumConstants) {
                        if (((MapEnum) enumConstant).getKey() == (int) fieldVal) {
                            field.set(obj, enumConstant);
                        }
                    }
                } else if (field.getType() == Boolean.class) {
                    field.set(obj, fieldVal instanceof Boolean ? fieldVal :
                            Integer.parseInt(fieldVal.toString()) == 1 ? true : false);
                } else {
                    field.set(obj, fieldVal);
                }
            } catch (IllegalAccessException e) {
                throw new BinaryObjectException("Failed to read enum field: " + field.getName(), e);
            }
        }
    }
}

2.指定ignite序列化器

代码如下(示例):

// IgniteThinClientConfig.java

@Bean
IgniteClientConfigurer configurer() {

    return cfg -> {
        // set self define serializer
        BinaryConfiguration binaryCfg = new BinaryConfiguration();
        binaryCfg.setSerializer(new IgniteSerializer());
        cfg.setBinaryConfiguration(binaryCfg);
        cfg.setPartitionAwarenessEnabled(true);
    };
}

至此配置结束。


总结

通过配置自定义ignite序列化器完美解决了我们的困境。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值