springboot luttuc redis 集成protobuf,手动序列化反序列化

news2024/11/24 19:52:14

前置需知:
1.本文章和网上大部分博客配置不太一样,各位看官要分析一下自己的需求。集成protobuf 本文章主要是手动调用protobuf的序列化方法,而不是交由springboot 去做,会偏向原生java 使用方式

2.由于为了和公司其他的项目达成一致,所以版本,依赖 都尽量保证一致,所以版本需要各位看官具体决定了哈(团队使用时不同版本会有冲突)
另外:看了网上用了protostuff https://blog.csdn.net/shenTiBeiTaoKongLa/article/details/107123596可以试一下(因为我没试,可以反馈成功与否哦)。

3.考虑到其他项目使用原生的luttuce,不支持key/value 结构不一致,所以对redis key field value 都进行压缩了(关注官网变更哦,后面会支持。或者看一下sprinboot-redis的源码(sprinboot支持的),对原生的Luttuce集成一下)在这里插入图片描述
在这里插入图片描述

4.由于初期设计的.proto文件,可能存在压缩不完全的问题(后面会具体聊),大家可以见仁见智了啊,欢迎反馈

话多说了,先上配置
pom依赖如下
<protobuf.version>3.24.0</protobuf.version>

  <dependency>
                <groupId>com.google.protobuf</groupId>
                <artifactId>protobuf-java</artifactId>
                <version>${protobuf.version}</version> <!-- protobuf -->
            </dependency>
            <dependency>
                <groupId>com.google.protobuf</groupId>
                <artifactId>protobuf-java-util</artifactId> <!--protobuf 工具类-->
                <version>${protobuf.version}</version>
            </dependency>
            <!-- Spring Data Redis -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
                <version>2.11.1</version> <!-- 请检查最新版本 -->
            </dependency>

继承RedisTemplate 对象 生成个性化RedisTemplate bean,配置序列化反序列化,自定义序列化RedisSerializer<byte[]> byteRedisSerializer = new RedisSerializer() 重写内部类是最核心的地方!

@Component
@AutoConfigureAfter(RedisAutoConfiguration.class)
@Import({RedisAutoConfiguration.class})
@Slf4j
public class ProtobufRedisTemplate extends RedisTemplate<Object, Object> {

    public ProtobufRedisTemplate( @Autowired() LettuceConnectionFactory lettuceConnectionFactory) {
        ProtobufRedisSerializer protobufRedisSerializer = new ProtobufRedisSerializer(Object.class);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        setConnectionFactory(lettuceConnectionFactory);
        afterPropertiesSet();
       **-- 重写RedisSerializer 序列反序列化方法,直接返回数据 ,核心!!!!**
        RedisSerializer<byte[]> byteRedisSerializer = new RedisSerializer() {

            @Override
            public byte[] serialize(Object o) throws SerializationException {
                if (o instanceof byte[]){
                    return (byte[])o;
                }
                return new byte[0];
            }

            @Override
            public byte[] deserialize(byte[] bytes) {
                return bytes;
            }
        };


        setKeySerializer(byteRedisSerializer);
        setValueSerializer(byteRedisSerializer);

        setHashKeySerializer(byteRedisSerializer);
        setHashValueSerializer(byteRedisSerializer);

        logger.warn("the Lettuce-protobuf starting success,date is -->"+ new Date());
    }
}

redis 工具类

@Component
@Slf4j
public class RedisUtils {

    @Autowired
    private ProtobufRedisTemplate protobufRedisTemplate;

    /**
     * HashSet 并设置时间
     * @param key 键
     * @param map 对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean p_hmset(byte[] key, Map<byte[], byte[]> map, int time) {
        try {
            protobufRedisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
        /**
     * HashGetAll
     *
     * @return 值
     */
    public Map<byte[], byte[]> p_hgetall(byte[] key) {
        Map<Object, Object> map = protobufRedisTemplate.opsForHash().entries(key);
        Map<byte[], byte[]> resultMap = map.entrySet().stream().collect(Collectors.toMap(entry -> (byte[]) entry.getKey(), entry -> (byte[]) entry.getValue()));
        return resultMap;
        //return protobufRedisTemplate.opsForHash().entries(key);
    }
}
    

测试的代码

        RedisData.RedisValue redisValue2 = RedisData.RedisValue.newBuilder()
                .putValue("master_id", createRedisObject("xxxx"))
                .putValue("item_code", createRedisObject(""))
                .putValue("content_id", createRedisObject("xxxx"))
                .build();

        final byte[] byteArray2 = redisValue2.toByteArray();
        //序列化

        Map<byte[], byte[]> test = new HashMap<>();
        final byte[] byteField1 = RedisData.RedisKey.newBuilder().setKey("xxxx").build().toByteArray();
        test.put(byteField1, byteArray);
        final byte[] byteField2 = RedisData.RedisKey.newBuilder().setKey("xxx").build().toByteArray();
        test.put(byteField2, byteArray2);

        byte[] bytes_key = RedisData.RedisKey.newBuilder().setKey("xxx").build().toByteArray();
        byte[] bytes_value = RedisData.RedisKey.newBuilder().setKey("xxx").build().toByteArray();

        redisUtils.p_hmset(bytes_value, test, 2592000);
        redisUtils.p_set(bytes_key, bytes_key, 2592000);

.proto文件数据结构如下(仅供参考):
这个是对可变的Map 进行压缩的,可能会压缩不完全
可以把map<string,RedisObject> value=1; 改成map<RedisKey,RedisObject> value=1;

syntax = "proto3";

package xxxx;
import public "google/protobuf/timestamp.proto";
option optimize_for=CODE_SIZE;
option java_outer_classname = "RedisData";

message RedisValue{
  map<string,RedisObject> value=1;
}


message RedisKey{
  string key=1;
}

message RedisObject{
  oneof value {
    string string_value = 1;
    int32 int_value = 2;
    double double_value = 3;
    google.protobuf.Timestamp Timestamp = 4;
  }
}

使用maven 将proto文件编译成java文件

 <os.detected.classifier>windows-x86_64</os.detected.classifier>
 <build>
        <extensions>
            <!--主要用于获取并设置与操作系统相关的属性-->
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.2</version>
            </extension>
        </extensions>
        <plugins>
            <!--protobuf plugins 插件-->
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>
                        com.google.protobuf:protoc:3.24:exe:${os.detected.classifier}
                    </protocArtifact>
                    <!--默认值,proto源文件路径-->
                    <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

在这里插入图片描述
使用方式:直接copy ,当做普通的java类使用就可以了,注意要和proto文件里面的package xxxx; 路径一致,否则会报错。

效果如下
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2125271.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QQueue调用dequeue闪退解决方法

QQueue调用dequeque闪退的解决方法 先看一下Qt帮助文档里面的说明 这个函数假设队列不是空的。 那么我们在调用之前&#xff0c;需要先判断队列是不是空的&#xff0c;如果不是空的&#xff0c;就调用该函数。 if (!queue.isEmpty()) {QString info queue.dequeue(); }这样…

【RabbitMQ 项目】Muduo 库快速上手

Muduo 库快速上手 一.Muduo 库简介二.五个常用类介绍三.结合 Protobuf 定制的应用层协议 一.Muduo 库简介 一句话概括&#xff0c;Muduo 库是基于非阻塞 IO 和事件驱动的 C 高并发 TCP 网络编程库。使用主从 Reactor 模型&#xff0c;使用的线程模型是是 one thread one loop R…

JWT令牌——详解

目录 一、JWT是什么&#xff1f; 二、JWT的组成 三、JWT应用场景 四、生成和校验JWT令牌 五、具体应用 一、JWT是什么&#xff1f; 在当今的Web开发中&#xff0c;安全认证和授权变得尤为重要。JWT&#xff08;JSON Web Tokens&#xff09;是一种开放标准&#xff08;RFC …

大厂中秋福利哪家强?字节发被子,京东联名三星堆!网友:最强的还是我们......

又是一年中秋佳节&#xff0c;大家公司发的中秋福利都拿到手了嘛&#xff1f; 从上周开始&#xff0c;各社交网络平台上就有人陆续晒出了公司发放的中秋礼盒。 其中&#xff0c;财大气粗的互联网大厂的礼盒尤为精致亮眼。 今天&#xff0c;小码就带大家一起来看看大厂那些让人…

在线机房迁移之“玩转TiDB迁移”

作者&#xff1a; 代晓磊_Mars 原文来源&#xff1a; https://tidb.net/blog/02df4029 要想搞定在线机房迁移之TiDB数据库迁移&#xff0c;看完本文基本上所有的迁移方案你都可以搞定了&#xff08;数据库迁移方案和流程大同小异&#xff09;。本文给了3种TiDB在线迁移的场景…

四款音频剪辑软件免费使用,你更pick哪一个?

视频剪辑知随着软件的不断更新&#xff0c;入门门槛和操作难度也随之变得越来越低&#xff0c;但是依然有不少人不知道剪辑视频要用什么工具&#xff0c;作为一个视频剪辑爱好者&#xff0c;我尝试过不少编辑软件&#xff0c;今天就来跟大家分享一下四款视频剪辑软件在实际使用…

我与Linux的爱恋:yum和vim以及gcc、gdb、git的使用

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;Linux的学习 文章目录 ​1.Linux软件包管理器yum2.Linux开发工具3.Linux编译器 vimvim的基本概念vim的基本操作vim正常模式命令集vim末行模式命令集vim操作总结批量化注释批量化去注释简…

Oracle反向键索引Reverse Key Index

Oracle反向键索引&#xff08;Reverse Key Index&#xff09;是一种特殊的B-Tree索引&#xff0c;它在创建索引时对索引列的键值进行字节反转。这种索引的主要设计目的是为了解决在多实例环境&#xff08;如Oracle RAC&#xff09;中由于索引键值顺序插入导致的索引块争用问题。…

Vue 3 watchEffect:如何用 onInvalidate 优化副作用处理

在 Vue3 中&#xff0c;watchEffect 是一个用于在响应式数据变化时自动重新执行的函数。它在创建响应式副作用时特别有用&#xff0c;比如在某些数据变化时更新 DOM、发起网络请求或处理复杂的逻辑。 watchEffect 的 onInvalidate 是一个非常重要的功能&#xff0c;用于处理副…

新闻资讯类APP流量变现技巧——提升广告变现收益

新闻资讯类APP拥有庞大的用户基础&#xff0c;始终拥有较强的广告变现能力&#xff0c;如何在激烈的行业竞争中凸显媒体的优势&#xff0c;进而吸引更多的广告主&#xff1f;优化核心场景广告样式的同时&#xff0c;挖掘更多的广告场景样式&#xff1f;如何把握好广告变现和用户…

“Interface 和 Type 区别”深度解析

“Interface 和 Type 区别”深度解析 文章目录 一、Interface 和 Type 是什么二、如何使用 Interface 和 Type1. 定义 Interface2. 定义 Type3. 使用 Interface 和 Type4. 区别与联系 三、Interface 和 Type 二者有哪些区别&#xff0c;分别在哪些场景使用1. 区别2. 场景 四、扩…

将Ruoyi框架系统的Swagger接口文档页面优化为knife4j风格

将Swagger文档原来的页面效果改成比较好看的knife4j风格文档页面 优化前&#xff1a; 请求地址&#xff1a;http://localhost:端口号/swagger-ui/index.html 优化后&#xff1a; 请求地址&#xff1a;http://localhost:端口号/doc.html#/home 修改步骤&#xff1a; 1.引入依…

CPU调度算法之优先级调度

点击下载《CPU调度算法之优先级调度》 摘要 CPU的优先级调度算法是一种通过为不同任务分配优先级来决定执行顺序的调度策略。这种算法使得系统能够优先处理那些被认为更重要或紧急的任务&#xff0c;从而提高整体效率和响应速度。然而&#xff0c;优先级调度也可能带来一些问…

快速求和

请编写程序&#xff0c;输入整数 n&#xff0c;快速计算&#xff1a; 输入格式 n 输出格式 s 要求&#xff1a;输出 6 位小数&#xff0c;末位四舍五入。 代码如下&#xff1a; #include<stdio.h> int main(){int n;double s;scanf("%d",&n);s1.0-1.0/(n1…

DeepACO:用于组合优化的神经增强蚂蚁系统

文章目录 Abstract1 Introduction2 Related work2.1 神经组合优化2.2 蚁群优化3 蚁群优化初探4 Methodology4.1 参数化启发式空间4.2 局部搜索与局部神经引导扰动交织4.3 训练启发式学习器4.4 更好的探索4.4.1 多头解码器4.4.2 Top-k熵损失4.4.3 模仿损失5 实验5.1 实验设置5.2…

DWS=管理员用户创建

管理员用户简介 管理员也称作系统管理员&#xff0c;是指具有SYSADMIN属性的帐户。 非三权分立模式下&#xff0c;拥有系统的最高权限&#xff0c;能够执行所有的操作。系统管理员具有与对象所有者相同的权限。管理员用户创建 su - omm source /opt/huawei/Bigdata/mppdb/.mpp…

【数据结构-二维前缀最小值】力扣3148. 矩阵中的最大得分

给你一个由 正整数 组成、大小为 m x n 的矩阵 grid。你可以从矩阵中的任一单元格移动到另一个位于正下方或正右侧的任意单元格&#xff08;不必相邻&#xff09;。从值为 c1 的单元格移动到值为 c2 的单元格的得分为 c2 - c1 。 你可以从 任一 单元格开始&#xff0c;并且必须…

2024年汉字小达人校内选拔的常见问题和解答

广受上海市小学生们关注的2024年第十一届汉字小达人的时间已经确定了&#xff0c;参赛的孩子们已经开始紧锣密鼓的准备中。 如昨天分析的2024年汉字小达人的赛程&#xff0c;即日起到10月20日是学校自行选拔的时间节点。9月25-30日是区级自由报名集中参赛的日子。两个日子有一…

中秋佳节,如何挑选实用有意义的礼物?精选中秋节最佳送礼清单!

当秋风送爽&#xff0c;丹桂飘香&#xff0c;我们即将迎来一年一度的中秋佳节。在这个充满温情与团圆的节日里&#xff0c;赠送礼物成为了表达我们对家人、朋友以及同事的关怀与祝福的重要方式。然而&#xff0c;面对琳琅满目的商品&#xff0c;如何挑选出既实用又有意义的礼物…

《现代食品》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问&#xff1a;《现代食品》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊。 问&#xff1a;《现代食品》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a; 中粮工程科技有限公司 主办单位…