大数据量数据传输与部分字段逻辑操作修改的高效实现
需求
此刻有一些呈现的表格, 其中部分字段存有加密的信息内容, 要经过解密操作之后, 存储到另外的某一个数据库当中。
有一些单表, 其数据量极大, 因服务器配置受限, 没办法一次性将其加载到内存里。
解密后的表被下游使用,解密效率上有要求。
或许数量方面加密的表会出现增加的情况, 加密字段同样也存在可能增加的情形, 开发结束之后能够手动去维护一张配置表, 自动进行解密与配置相关加密表以及对应表字段的操作。
实现目标
大数据量情况下服务使用正常
最大化利用资源提升解密速度
自动适配多表(无需根据数据源表结构变化进行额外编码开发)
问题拆解
先从资源利用出手
非常显著地, 一条数据历经服务的生命周期被划分成三个耗费时间的阶段, 这三个阶段分别是数据加载阶段, 数据解密阶段, 数据写出阶段。
于单线程起始之处, 当有一个线程着手加载数据之际, 它是没有办法针对其他已然加载好的数据去实施解密操作的, 同样的道理, 当线程处于数据解密阶段时, 它没办法把已经解密好了的数据向外输出。所以呢便选用了经典的生产 - 消费模型, 是将三个耗时阶段分成三个线程组所构成的模块, 各个模块之中处于线程状态的部分在处理完自身的相应任务之后会直接朝着下游扔出去, 线程组所形成的这些模块之间借助着java里面本身就有的处于线程安全状态的阻塞队列来开展数据方面的交互行为, 可别忘了阻塞队列是有着分段锁设计的, 模块彼此之间的交互依旧是并行的状态。
随即瞧一瞧单表超大数据量会致使怎样的状况(全量载入内存会引发内存溢出那般的状况), 假定数据加载线程组模块里各个线程所分配的任务单元是表, 总归会有线程获取到单表超大数据量的任务进而造成服务的直接奔溃, 因而数据加载的任务单元应当是表分片, 然而配置的表需求者没办法给出主键, 依据什么进行分片呢? 数据库存在内置字段ctid, 在离线的场景当中, 数据没有变化状况下, 每一条数据都具备唯一的ctid, 同时恰好数据处于块上的分布颇为均匀, 所以能够依据ctid来进行分片, 并且是从连续的磁盘地址那里获取到校数据。
好像资源利用以及内存溢出情形已然得到解决, 事实上内置的阻塞队列默认是没有边界限定的, 也就是说三个线程组模块要是处理速率存在交大差距, 那就会致使处理速度迟缓的模块与上级模块之间的阻塞队列超出服务器内存配置, 从而使服务遭受崩溃, 好在借助设置内置的阻塞队列最大存有容量加以限制, 能够非常好地防止此类问题出现。但是为了提升线程的使用效率, 需要对线程组模块参数进行调整, 给予花费时间较多的模块更多数量的线程, 一直到遭遇服务器性能瓶颈(理想状况是服务器带宽达到饱和状态, 并且还有剩余的内存以及cpu资源)。
要说适配多表, 那解决方式相对而言是比较易于处理的, 在借助jdbc拉取数据之际, 字段元数据跟存储的业务数据索引是保持一致的, 将一行的数据直接予以封装而成为一个map, 使其在线程组之间进行流转便可, 对于那些需要进行解密的字段, 仅仅实施O1时间复杂度的get操作来完成解密后再放回去即可。对于java的内存回收机制而言, 在生产消费模式里, 对象创建与销毁十分频繁, 借助Pool技术, 在数据加载阶段, 数据载体是从pool中获取, 到了数据写出阶段, 原本的销毁操作能够替换成pool回收, 如此一来, 内存回收的开销基本上就能够被忽略掉了。
基础结构

扩展表分片的几种方式
1.有着这样一个情况, 数据库它天然就存在着内置字段ctid, 其结构呈现为(块号, 元组索引) , 是(0, 1)这样一种具体的形式。
位于最开始的那个值(): 其为数据所占的数据块编号( 当中的数据是以固定大小的块来进行存储的, 默认的块大小是 8KB)。块号是从 0 开始算的, 依照物理顺序逐步递增。
第二个值, 它是指数据块内的元组索引, 也就是行在块内的位置。每个数据块能够储存多个行, 也就是元组, 并且索引是从1开始的。
2.()
3.主键分片
更多推荐
所有评论(0)