首页 > 其他分享 >0-7 RowKey 设计

0-7 RowKey 设计

时间:2023-02-04 11:12:39浏览次数:39  
标签:userid 索引 RowKey 设计 HBase data 主键

RowKey 设计

RowKey 概念

HBase 中 RowKey 可以唯一标识一行记录, 在 HBase 查询的时候有以下几种方式:

  • 通过 Get 方式, 指定 RowKey 获取唯一一行记录

  • 通过 Scan 方式, 设置 startRow 和 stopRow 参数进行范围匹配

  • 全表扫描, 直接扫描表中所有行记录

从字面意思来看, RowKey 就是行健的意思, 在增删改查的过程中充当了主键的作用, 它可以是任意字符串, 在 HBase 内部 RowKey 保存为字节数组.

HBase 中的数据是按照 RowKey 的 ASCII 字典顺序进行全局排列的, ASCII 字典顺序举一个例子:

假如有 5 个 Rowkey:"012", "0", "123", "234", "3",按 ASCII 字典排序后的结果为:"0", "012","123", "234", "3"

因此我们设计 RowKey 时,需要充分利用排序存储这个特性,将经常一起读取的行存储放到一起,要避免做全表扫描,因为效率特别低。

多条件查询

假设一个场景. 用户每天产生的消息用如下 RowKey 表示: userid-data-messageid. 我们查询一个用户所有天的消息记录可以匹配 userid-, 但是当我们需要查询一天所有用户发的消息记录的话就需要匹配 -data-, 这样 B+ Tree 就无法索引, 从而只能全表扫描.

为了解决以上问题, 我们回想一下 MySQL 非主键索引的查询方式, 每一个非主键索引都维护着一个 B+ Tree, 叶子节点上存放的是索引值和主键值, 然后通过主键值进行二次查找主键索引的 B+ Tree 找到一行的值.

所以我们也可以借鉴这种方法, 为每一个索引维护一个索引表. 比如匹配 -data-, 就将索引表的 RowKey 存为 data-userid-messageid, 这一行的值为 "data, userid, messageid, 原表的RowKey". 这样我们就可以使用索引表的 RowKey 匹配到符合 -data- 匹配条件的 userid-data-messageid(原表的RowKey), 再根据这些原表的 RowKey Get 查找所有的行记录.

数据热点

糟糕的 RowKey 设计是热点的源头, 会使得大量 Client 访问集群中的一个或者几个节点, 这样会使得热点机器服务几乎不可用.

所以我们应该优化 RowKey 的设计, 使数据被写入到集群的多个节点, 而不是一个.

在实际使用中, 主要有两个方法来避免热点问题: 反转 RowKey, 加前缀.

反转 RowKey

反转 RowKey 这个字节数组.

以手机号为例子, 手机号前缀的变化少 (158, 159 等), 如果正常存储极极有可能被存放在一个节点上. 手机号后半部分变化很大, 所以我们采用反转的方式让其均匀分布.

加前缀

将原本写好的 RowKey 计算哈希值, 然后将运算后的哈希值作为前缀用来 "打散" 数据.

RowKey 长度

我们在检索的时候, RowKey 是要作为 B+ Tree 节点值来索引的. 如果 RowKey 过长, 那么内存中存放的索引就越少, 影响效率. 另外, 我们目前使用的服务器都是 64 位的, 内存是按照 8Byte 对齐的, 因此设计 RowKey 是一般做成 8Byte 的整数倍, 如 16Byte 或者 24 Byte, 可以提高寻址效率.

标签:userid,索引,RowKey,设计,HBase,data,主键
From: https://www.cnblogs.com/geraldkohn/p/17091091.html

相关文章

  • 7 视频流系统设计
    视频流系统设计设计YoutubeScenario月活跃用户(MAU):20亿日活跃用户(DAU):1.5亿每天观看视频数量:50亿每分钟上传视频时长:500个小时用户平均观看时间:40分......
  • 4 短网址设计
    短网址设计Scenario需求ApplyShortURLgraphLRA(用户)-->|http://www.jiuzhang.com|B(http://bit.ly)B-->|http://bit.ly/1UloQB6|A根据ShortURL还原Lo......
  • Java程序设计基础复习题
    Java程序设计基础1-6一、Java语言概述1.Java语言有哪些特点?简单易学。Java去掉了C/C++语言支持的单个不易理解和掌握的数据类型(指针pointer、联合体unions、结构体stru......
  • 深度剖析 Linux 伙伴系统的设计与实现
    在上篇文章《深入理解Linux物理内存分配全链路实现》中,笔者为大家详细介绍了Linux内存分配在内核中的整个链路实现:但是当内核执行到get_page_from_freelist函数,......
  • 设计模式
    一、单例模式因为在编程开发中经常会遇到这样⼀种场景,那就是需要保证⼀个类只有⼀个实例哪怕多线程同时访问,并需要提供⼀个全局访问此实例的点。综上以及我们平常的开......
  • day03-203.移除链表元素|707.设计链表|206.反转链表
    203.移除链表元素leetcode题目:https://leetcode.cn/problems/remove-linked-list-elements/题目描述:给你一个链表的头节点head和一个整数val,请你删除链表中所有满足......
  • 亲身开发一个Windows软件(三)界面设计
    现在,我们已经准备好了,要开始开发了。首先我们要进行界面设计。从某种方面来说,这比写代码更重要,因为用户只会感觉到界面,而不会在乎代码,所以一个好的用户界面,是一个优秀软件......
  • 《Vue.js 设计与实现》读书笔记 - 第8章、挂载与更新
    第8章、挂载与更新8.1挂载子节点和元素的属性扩展子元素的类型可以为数组,并判断如果是数组的话,就先依次挂载所有的子元素。同时新增节点属性。属性可以通过el.setAttr......
  • LeetCode刷题,代码随想录算法训练营Day3| 链表理论基础 203.移除链表元素 707.设计链
    链表理论基础链表是通过指针串联在一起的线性结构,每个节点由一个数据域和一个指针域构成。链表的类型单链表双链表有两个指针域,一个指向下一个节点,一个指向上一个节......
  • 【RUST程序设计语言】第八章 常见集合练习题 Pig Latin
    题目摘录:给定一系列数字,使用vector并返回这个列表的中位数(排列数组后位于中间的值)和众数(mode,出现次数最多的值;这里哈希map会很有帮助)。将字符串转换为PigLatin,也......