REST API 方式主要被用作 HTTP 或者 HTTPS 协议的接口定义,即使在非微服务架构体系下,也被广泛采用。由于 HTTP 本身就是公开标准网络协议,所以几乎没有什么额外学习成本。
代表 RPC 框架:Spring Cloud Eureka
XML 配置
XML 配置方式通过在服务提供者和服务消费者之间维持一份对等的 XML 配置文件,来保证服务消费者按照服务提供者的约定来进行服务调用。在这种方式下,如果服务提供者变更了接口定义,不仅需要更新服务提供者加载的接口描述文件 server.xml,还需要同时更新服务消费者加载的接口描述文件 client.xml。但这种方式对业务代码侵入性比较高,XML 配置有变更的时候,服务消费者和服务提供者都要更新,所以适合公司内部联系比较紧密的业务之间采用。
HBase 自动将表水平划分成区域(Region)。每个 Region 由表中 Row 的子集构成。每个 Region 由它所属的表的起始范围来表示(包含的第一行和最后一行)。初始时,一个表只有一个 Region,随着 Region 膨胀,当超过一定阈值时,会在某行的边界上分裂成两个大小基本相同的新 Region。在第一次划分之前,所有加载的数据都放在原始 Region 所在的那台服务器上。随着表变大,Region 个数也会逐渐增加。Region 是在 HBase 集群上分布数据的最小单位。
HBase 数据模型示例
下图为 HBase 中一张表的:
RowKey 为行的唯一标识,所有行按照 RowKey 的字典序进行排序;
该表具有两个列族,分别是 personal 和 office;
其中列族 personal 拥有 name、city、phone 三个列,列族 office 拥有 tel、addres 两个列。
List<Long> list = new ArrayList<>(); list.add(1554975573000L); TimestampsFilter timestampsFilter = new TimestampsFilter(list); scan.setFilter(timestampsFilter);
Column Family 数量多,会影响数据刷新。HBase 的数据刷新是在每个 Region 的基础上完成的。因此,如果一个 Column Family 携带大量导致刷新的数据,那么相邻的列族即使携带的数据量很小,也会被刷新。当存在许多 Column Family 时,刷新交互会导致一堆不必要的 IO。 此外,在表/区域级别的压缩操作也会在每个存储中发生。
Column Family 数量多,会影响查找效率。如:Column Family A 有 100 万行,Column Family B 有 10 亿行,那么 Column Family A 的数据可能会分布在很多很多区域(和 RegionServers)。 这会降低 Column Family A 的批量扫描效率。
Column Family 名尽量简短,最好是一个字符。Column Family 会在列限定符中被频繁使用,缩短长度有利于节省空间并提升效率。
Row 设计
HBase 中的 Row 按 Row Key 的字典顺序排序。
不要将 Row Key 设计为单调递增的,例如:递增的整数或时间戳
问题:因为 Hbase 的 Row Key 是就近存储的,这样会导致一段时间内大部分写入集中在某一个 Region 上,即所谓热点问题。
Connection Pooling For applications which require high-end multithreaded access (e.g., web-servers or application servers that may serve many application threads in a single JVM), you can pre-create a Connection, as shown in the following example:
对于高并发多线程访问的应用程序(例如,在单个 JVM 中存在的为多个线程服务的 Web 服务器或应用程序服务器), 您只需要预先创建一个 Connection。例子如下:
// Create a connection to the cluster. Configuration conf = HBaseConfiguration.create(); try (Connection connection = ConnectionFactory.createConnection(conf); Table table = connection.getTable(TableName.valueOf(tablename))) { // use table as needed, the table returned is lightweight }
A clusterconnection encapsulating lower level individual connections to actual servers and a connectionto zookeeper. Connections are instantiated through the ConnectionFactory class. The lifecycle of the connectionis managed by the caller, who has toclose() the connection torelease the resources.
// 写入单行 put voidput(Put put)throws IOException; // 批量写入 put voidput(List<Put> puts)throws IOException;
Put 类提供了多种构造器方法用来初始化实例。
Put 类还提供了一系列有用的方法:
多个 add 方法:用于添加指定的列数据。
has 方法:用于检查是否存在特定的单元格,而不需要遍历整个集合
getFamilyMap 方法:可以遍历 Put 实例中每一个可用的 KeyValue 实例
getRow 方法:用于获取 rowkey Put.heapSize() 可以计算当前 Put 实例所需的堆大小,既包含其中的数据,也包含内部数据结构所需的空间
KeyValue 类
特定单元格的数据以及坐标,坐标包括行键、列族名、列限定符以及时间戳 KeyValue(byte[] row, int roffset, int rlength, byte[] family, int foffoset, int flength, byte[] qualifier, int qoffset, int qlength, long timestamp, Type type, byte[] value, int voffset, int vlength) 每一个字节数组都有一个 offset 参数和一个 length 参数,允许用户提交一个已经存在的字节数组进行字节级别操作。 行目前来说指的是行键,即 Put 构造器里的 row 参数。
客户端的写缓冲区
每一个 put 操作实际上都是一个 RPC 操作,它将客户端数据传送到服务器然后返回。
HBase 的 API 配备了一个客户端的写缓冲区,缓冲区负责收集 put 操作,然后调用 RPC 操作一次性将 put 送往服务器。