当前开发项目需求:需要上链一天10万条数据,后台使用网关暴露服务
(只是一家ISV10万,后期可能数据量非常大,需要转移数据)
(区块链溯源Baas平台,提供安全管理服务)
一、单条数据请求,数据验证后发送到链上同步返回。
二、批处理支持两百条同时请求,简单验证后入消息队列异步返回。(考虑数据上链需要大概2秒的时间,批处理不可能瞬时返回)
- sql一条语句验证(重复)时间(查询)大概为0.36秒,若是200条则为7秒左右。产品网关10秒返回超时返回失败,需要对数据key做幂等处理,并且校验数据key重复(可能会出现网关重试,用户重复发送)。
优化:使用批处理插入数据,数据设置unique key,时间大概1秒左右。成功则插入,失败则校验失败。
- 阿里云公有云产品rocketmq发送一条数据(1k)时间为0.8-1.3秒左右,200条时间约为16-26秒左右。
优化:验证发现发送大量数据(1M)到消息队列的时间也和一条数据(1K)基本一致,直接发送200条数据一次性发送到mq,由于200条数据一次性处理对服务器影响不是很大,并且总共有10万条数据,所以大概率不会出现一台消费服务器负载很大的情况。
- tomcat连接池默认大小为200,消息队列线程大小为20,druid连接池大小设置为20,等待时间为1秒。
优化:碰到问题druid线程池太小,等待时间太短导致出现问题,改为设置druid连接池大小为100,等待时间为60秒。(极 端情况下可能会出现消息生产方占用druid线程,消费方无法及及时获取线程导致异常)
- 单批次数据更新200条 * 0.07s需要花费14s时间
优化:由于一个批次都是一个最终状态,所以把循环修改部分数据放到一起,用in代替=,最终花费0.1s - 0.2s。
- 由于是Iot项目,所以数据量较大,现阶段优化目标为100tps,将来可能会要求10000tps。带宽要求非常高 70KB * 100 = 7MB,10000 * 70KB = 700MB,对GC也是一种考验。
- 优化对象复制,减少大对象的复制直接使用原本对象。
- 优化数据传输发送队列的大小,减少发送时间和消费端GC对象的大小。
- 使用useGeneratedKeys代替SelectKey,批量添加返回数据Id(只能使用数据库自增id)。
三、消息队列消费消息上链。
- 消费端服务器消息幂等处理
1、RDS实现(线上第二版本需要快速迭代,所以先采用数据库进行。申请Redis流程复杂)
创建分布式锁数据库表,查询时锁定指定行记录。上链后开放记录,再次进行当前数据状态查询。
优化:直接在第一条记录做中间状态,用update + where只放开一条记录的通行,不需创建分布式锁表,且减少数据查询时 间。
2、Redis实现
暂时未使用
- 确保数据成功上链,成功或失败是数据表记录更新状态。
优化:添加重试机制,上链部分重试一定次数。
- rocketmq消费者启动了20个线程处理数据,测试服务器使用2核4G 2台服务器分布式配置,频繁分配内存导致服务器宕机 平均3秒左右会触发一次GC(minor gc)。
消费者线程过多,修改消费者线程为4个线程,采用2台4核8G服务器测试服务。修改配置服务后只运行消费者GC平均触发 频率在20秒一次。
- 优雅下线
1、批处理异步消息
利用rocketmq设置的消费超时时间,和设置幂等中间状态的时间判断消息是rocketmq超时消息重发还是初次发送来进行批处 理子项的上链操作。
2、单条同步消息
利用服务器启动查询单条类型的消息,若是为未处理则进行上链操作。
- 测试数据库数据最大连接60,测试sdk压测100线程出现insertBatch阻塞大量时间。
修改压测线程为40左右,线上连接为2000故无影响
- 数据反序列化时直接使用字节构造避免转换String导致过程中占用GC对象。