hashmap与分库分表技术

HashMap

在java的数据结构类库中提供了java.util.HashMap数据结构。它的数据存储结构为数组+单向链表。

  • HashMap的初始容量为16即数组的长度。

对于HashMap中的数组,我们可以将每个数组位置看作一个桶。每个桶即为实际数据的存储容器。HashMap使用单向链表来实现这个桶容器。

HashMap的存储值步骤(put):

  1. 当有数据需要存储在HashMap中时,则首先应用hash函数,对其key求取hash值;
  2. 然后与桶个数取模,获取到应当将值存储在数组的索引,即桶的位置;
  3. 在桶中应用单向链表进行相应的值存储;
  4. 判断是否需要进行数组长度扩容,如果需要则进行2倍数组长度扩容,然后进行数据重hash;
  5. 完成了本次数据的存储;

HashMap的数据读取步骤(get):

  1. 当使用相应的key,获取对应的值时,首先应用hash函数,对key进行取hash值;
  2. 然后与桶个数取模,获取到桶的索引位置;
  3. 遍历桶的容器实现单向链表中的所有值对应的key,获取对应的值内容返回前端;
  4. 完成本次的数据读取;

对于jdk8以后的hash存储,对于单个桶的数据量超过一个阀值之后采用红黑树结构进行存储,即桶中的数据量较少时采用单向链表;而当桶中的数据量较大时则采用红黑树结构进行数据的存储。这种数据结构改造主要是因为单向链表的数据读取速度较慢为O(n),而红黑树的数据读取速度为O(lgn).对于红黑树结构,我们先不深入讨论,后期有机会再说。

分库分表

在互联网电商中,当单个数据库(这里只考虑关系数据库)或单表的数据量太大,则需要使用分库分表技术来解决相应的问题。

为什么将HashMap与分库分表放在一起写呢?主要是为了脑洞大开,我们是否可以应用HashMap的实现思路来设计分库分表方案。

对于分库分表,主要需要解决如下问题:

  • 分多少个库?即解决库的容量问题;
  • 分库之后,数据处理库的定位问题;
  • 分库之后数据的读取;
  • 分库之后数据的写入;
  • 分库之后如何扩容;
  • 细节问题还有很多比如数据聚合,分布式事务等,这里只考虑主要思路

我们可以参考HashMap的实现思路,设计一个分库分表组件,每个部分相应的解决方案(对比如下):

参数 HashMap 分库分表
容量(这个数为2的n次方) hashMap存储数组的长度(初始值为16) 需要分的数据库个数
hash函数 key的hash值计算 分库策略
取模 桶的位置定位 分库策略
数据读取 遍历单向链表 jdbc读取数据
数据写入 写入单向链表的尾部 jdbc写入数据库
扩容 在写入之后需要即扩容,并成倍的扩容 可以适时扩容,通过容量监控

容量,对于分库分表我们可以根据业务的实际数据量增长速度,可以进行提前预估算,以得出最初始的分库容量;

分库策略:在分库分表中,比如我们采用会员id,则相应的id值即可作为hash值,即不需要hash函数计算;然后能过取模操作获取对应的分库位置;当然也可以采用一致性hash算法,为后期的数据库扩容打基础;

分库扩容:可以通过容量监控,在请求量相对较低的时候进行扩容;而不需要像HashMap那样写后需要即扩容,而影响系统的响应性能。

猜你喜欢

转载自blog.csdn.net/zhurhyme/article/details/77799270