实时数据处理
Part1.nosql数据库概念
1.1.nosql数据的基本介绍
nosql型数据库,也将其称为 非关系数据库,有区别去于关系型数据库,在非关系型数据库中,不存在表关系,大部分非关系型数据库不支持SQL查询,不支持复杂的查询方案,不支持多行事务部处理,仅支持单行事务处理.
优点:读写性能非常高,常常被用于 缓存操作
适用场景:
- 高并发的读写
- 海量数据读写
- 高可扩展性
- 速度快
常见的nosql数据库:redis,HBASE,MongoDB…
Part2.redis数据库基本介绍
2.1.redis的概念
redis是一款基于C语言开发的一款开源免费的支持数据持久化的key-value
型数据存储(有别于MySQL的二维表形式的数据 存储)的nosql型数据库,同样支持多种数据类型.
2.2.redis的应用场景
-
获取最新N个数据的操作
-
排行榜应用,取TOP N 操作
-
需要精准设定 过期时间的应用
-
计数器应用
-
…
2.3.redis的特点
-
高效性(redis的读写性能非常的高);
-
redis支持多种数据形式:
主要有五种数据类型: string ,hash, list , set ,sorted set
注意: redis的数据类型主要指的是redis中key-value中value的数据类型, 而key只有string -
原子性(redis的中所有的操作都是原子性的,用于保证数据的完整性)
-
redis的数据移植非常的方便,非常的稳定(一般redis不容易出现宕机)
2.4.redis的相关的shell命令操作
2.4.1.string数据类型
添加数据:set key value
获取数据:get key
数值增减操作:
incr:自增 +1
incrby:指定 + 具体的数值
decr:自减 -1
decrby:指定 - 具体的数值
拼接value值: append key value
为key中内容设置有效时长:
-为新创建的key设置时长
-setex key seconds value
-为已有的key设置有效时长
-expire key seconds
判断key是否存在: exists key
-返回1 表示存在, 返回0 表示不存在
获取key还剩余有效时长: ttl key
-特殊: 返回-1表示永久存在,返回-2表示不存在
2.4.2.hash数据类型
存储对象(javaBean)更加的方便--但是不一般不使用此类型存储对象, 一般会使用string, 为什么嘛?
因为 可以在Java中 将对象 直接转换为 Json(具有一定格式的字符串)
-存值: hset key field value
-key 为一个字符串,value类似于map,同样有一个field和value
-取值:
-获取指定的key的field的值:hget key field
-获取指定key的多个field值:hmget key field
- 存值: hset key field value
- key为一个字符串, value类似于map,同样有一个field和value
- 取值:
- 获取指定key的field的值: hget key field
- 获取指定key的多个field值: hmget key fields
- 获取指定key中的所有的field与value的值: hgetall key
- 获取指定key中map的所有的field: hkeys key
- 获取指定key中map的所有的value: hvals key
-删除: hdel key field [field … ]
-判断某个key中的filed是否存在: hexists key field
返回 0表示没有, 返回1 表示有
-获取key中所包含的field的数量: hlen key
2.4.3.list数据类型
本质就是一个队列,而队列可以满足特性FIFO
应用场景:任务队列
-添加:
-从左侧添加:lpush key values[value1 value2...]
-在指定的key所关联的list的头部插入所有的values,如果该key不存在,该命令在插入的之前创建一个与该key关联的空链表,之后再向该链表的头部插入数据。插入成功,返回元素的个数。
-从右侧添加:rpush key values[value1 value2...]
-在该list的尾部添加元素
- 查看列表 : lrange key start end
- 获取链表中从start到end的元素的值,start、end从0开始计数;end可为负数,若为-1则表示链表尾部的元素,-2则表示倒数第二个,依次类推…
- 删除(弹出):
- 从左侧弹出:lpop key
- 返回并弹出指定的key关联的链表中的第一个元素,即头部元素。如果该key不存在,返回nil;若key存在,则返回链表的头部元素
- 从右侧弹出: rpop key
- 从尾部弹出元素
- 获取列表中元素的个数: llen key
- 返回指定的key关联的链表中的元素的数量
- 向指定的key插入数据, 仅在key存在时插入, 不存在不插入
- 从左侧:lpushx key value
- 从右侧: rpushx key value
- lrem key count value:
- 删除count个值为value的元素,如果count大于0,从头向尾遍历并删除count个值为value的元素,如果count小于0,则从尾向头遍历并删除。如果count等于0,则删除链表中所有等于value的元素
- lset key index value:
- 设置链表中的index的脚标的元素值,0代表链表的头元素,-1代表链表的尾元素。操作链表的脚标不存在则抛异常。
- linsert key before|after pivot value
- 在pivot元素前或者后插入value这个元素。
- rpoplpush resource destination
- 将链表中的尾部元素弹出并添加到头部。[循环操作]
2.4.4.set数据类型
set集合特点:无序 去重
应用场景:去重操作
-添加:sadd key values [value1 value2...]
-删除:srem key members[menber1、menber2...]
-获取所有的元素: smembers key
-判断元素是否存在: sismember key member
-获取set中成员的数量:scard key
2.4.5.sortedset数据类型
sortedset特点:有序 去重
应用场景:专门是为排行榜而应用而生
-添加数据:zadd key score1 member1 [score2 menber2...]
-获取元素:
-zscore key member: 返回指定元素的得分
-zcard key :获取集合中的成员数量
-删除元素:zrem key member
-判断某个成员的排名情况:
zrank key member: 返回指定元素的额排名情况(从小到大)
zrevrank key member:返回指定元素的排名情况(从大到小)
-范围查询:
zrank key start end [withscores]
查询指定范围的排名信息(从小到大)
zrevrange key start stop [withscores]
查询指定范围的排行信息(从大到小)
--notice!!!
如果带上 withscores 表示结果是否要带上得分信息
0表示从第一个排名
-1 表示最后一名
2.4.6.通用的key的操作
-查看所有的key: keys *
-删除key: del key
-对指定key设置有效时间: expire key seconds
-获取key还剩余有效时长: ttl key
特殊: 返回-1 表示永久有效 返回-2 表示不存在
-判断key是否存在:exists key
返回-1 表示永久有效 返回-2 表示不存在
2.5.redis的持久化
-
持久化:从内存将数据写入到磁盘的过程称为持久化(序列化,钝化)
-
反序列化(活化):从磁盘到内存的过程
-
为什么redis要 进行持久化?
redis的数据都是存储在内存中,当服务器宕机或者关机,都会使内存中的数据丢失,此时redis中的数据也会丢失,将数据持久化到磁盘中,下次 再启动redis的时候,从磁盘中将数据恢复到内存中来,所以说,redis能否存储更多的数据,取决于所在服务器的内存大小
-
redis为了实现持久化的操作,提供了两种持久化机制: RDB 和 AOF
-
RDB: 基于快照机制
将redis的数据在内存的一个状态信息保存到磁盘中,形成一个RDB 的持久化的文件
优点:快照 文件的大小一般比较小,适合于进行灾难性恢复
缺点:由于RDB机制的原因,存在数据丢失的问题
-
AOF:基于日志机制,将每次操作(增删改)redis的命令都保存你到AOF的日志文件中,保持的数据相对更加完整一些
优点: 数据更加完整,丢失数据的问题比较小
弊端:日志文件一般都是比较大的,不利于进行灾难恢复,且较大的影响redis的性能
redis 默认情况下使用的是RDB持久化的方案,AOF 默认是关闭的
-
2.6.redis的主从复制架构
2.6.1 主从复制原理
- 当从数据库启动后,会向主数据库发送SYNC命令
- 主数据库接收到SYNC命令后开始在后台保存快照(RDB持久化),并将保存快照期间接收到的命令缓存下来.
- 快照完成后,Redis(Master)将快照文件和所有缓存的命令发送给从数据库
- Redis(Slave)接收到RDB和缓存命令时,会开始载入快照文件并执行接收到的缓存的命令
- 后续,每当主数据库接收到写命令时,就会将命令同步给从数据库。所以3和4只会在初始化的时候执行.
2.6.2 主从复制的应用场景
- 实现读写分离,以提高服务器的读写能力(主节点负责写入,从节点负责读取操作)
- 当单机Redis无法应付大量的读请求时(尤其是消耗资源的请求),就可以通过主从复制功能来建立多个从数据库节点,主数据库只进行写操作,从数据库负责读操作
- 这种主从复制,比较适合用来处理读多写少的场景,而当单个主数据库不能满足需求时,就需要使用Redis 3.0后推出的集群功能.
2.6.3.哨兵模式
-
哨兵模式主要用来解决主从复制架构中,主节点宕机后,无法切换某个节点成为主节点的问题
-
通过在每个 节点上启动一个哨兵进程,使用哨兵一直监控这主节点,当主节点宕机后,由哨兵来选举一个节点成为主节点.
-
思考题
-
主从架构 和 哨兵模式 是否能够对redis进行横向扩展?
答:并不会,只是对redis的进行纵向扩展,提升redis的读取的性能
-
如果redis的数据库比较多, 已经超出主节点内存大小了, 如何解决呢?
解决方案:
1)提升服务的内存大小(并不是最终方案)
2)利于大数据系统(分布式思想):
使用多台机器共同完成数据的存储,构建redis的集群
-
2.6.4.redis 集群
-
实现redis集群化的原因
- 主从复制不能实现高可用
- 数据量的考虑,现有服务器内存不能满足业务数据的需要时,单纯向服务器添加内存不能达到要求,此时需要考虑分布式需求,把数据分布到不同服务器上
- 网络流量需求,业务的流量已经超过服务器的网卡的上限值,可考虑使用分布式来进行分流
-
常用的数据 分布式:
- 顺序分布: 关系型数据库的设计
- 哈希分布:
- 哈希取模
- 一致性哈希
- 预设hash槽(redis使用此种方式)
Part3.HBase数据库基本介绍
2.1.HBase的基本介绍
2.1.1.hbase的概念及特点:
- HBase是 BigTable 的开源java版本。是建立在HDFS之上, 也就是说要想安装启动hbase必须先保证hadoop启动良好的,数据最终都是存储在 HDFS上,hbase也是一款nosql型的数据库, hbase本身不支持SQL的操作, 不支持多行的事务, 仅支持单行的事务操作,不支持join 不支持复杂查询
- HBase仅能通过主键(row key)和主键的range来检索数据
hbase中查询数据的方式主要三种:- 通过主键(row key)查询数据
- 通过 主键的范围查询数据
- 查询所有的数据
- 主要用来存储结构化和半结构化的松散数据
- Hbase中支持的数据类型:byte[]
- HBase中的表一般有这样的特点
- 大:一个表可以有上十亿行,上百万列
- 面向列:面向列(族)的存储和权限控制,列(族)独立检索
- 稀疏:对于为空的列,并不占用存储空间,因此,表可以设计的非常稀疏(稀疏表)
- hbase的应用场景:
数据需要进行高效的随机读写的场景, 数据量比较庞大 可以尝试使用hbase来解决 - hbase的特点:
- 强一致性读/写
- 自动分块
- 自动RegionServer故障转移
- Hadoop/HDFS集成
- 可以和MapReduce集成
- Java Client API
- Thrift/REST API
- 块缓存和布隆过滤器
- 运行管理(提供管理界面)
2.2.HBase的表模型
1).table: hbase的表 支持有多个表
2).rowkey: 行键 看做是 RDBMS中主键,
行键的类型都是字节的方式, 行键对应的这一列数据都自动按照字典序的升序排序
3).column family: 列族 看做是RDBMS中的列 一个列族下面可以有多个列(支持上百万个)在构建一张表的时候, 列族一般不建议过多, 在能满足要求的情况下, 能写一个解决, 坚决不写两个因为 列族越多, 在后续读写操作的时候, 经历的IO就会越大, 导致效率降低
注意: 在创建一张表的时候, 必须携带两个参数: 表名 + 列族
4).column : 列 (列的限定符号) 在hbase中, 一个列只能被一个列族所管理 一个列族下可以有多个列列在插入数据的时候, 可以动态的话指定 需要有那些列即可, 并不需要创建时候指定
5).cell : 单元格
如何确定一个唯一单元格: rowkey + 列族 + 列名 + 列值
6).timeStamp : 时间戳
在向hbase操作据的时候, hbase默认会将当前操作的时间记录下来
7).versionNum : 版本号
hbase支持对每一条数据或者说每个列族下的数据, 定义其版本号, 版本号 主要目的就是为了
表示是否需要存储数据历史变化信息, 已经存储多少个问题
2.3.shell命令
2.3.1.如何创建表格
语法:create '表名' , '列族' , '列族2' ...
2.3.2.如何查看表
语法:list 即可
2.2.3.如何向表中插入数据
语法:put '表名' , '行键' , '列族:列名' , '值'
2.2.4.如何查看某一条数据
语法:get '表名' , '行键' [,'列族' | '列族:列名' ...]
ex: get 'ORDER_INFO', 'rk0001'
get 'ORDER_INFO', 'rk0001' ,'C1'
get 'ORDER_INFO', 'rk0001' ,'C1','C2'
get 'ORDER_INFO', 'rk0001' ,'C1:name','C2'
get 'ORDER_INFO', 'rk0001' ,'C1:name','C2:birthday'
get 'ORDER_INFO' ,'rk0002' ,{FORMATTER => 'toString' } --如果有中文 可以加入
2.2.5.修改数据
语法:put '表名' , '行键' , '列族:列名' , '值'
注意: 修改数据和 添加数据是一致的, 如果hbase中已经存在, 那就是修改了, 如果不存在就是添加操作
2.2.6.如何删除数据
delete | deleteall
delete '表名' , '行键' , '列族:列名'
deleteall '表名' , '行键'
ex:delete 'ORDER_INFO','rk0001' ,'C2:sex'
notes!!!
1. deleteall 是在 hbase 2.0版本后出现的, 在2.0版本之前, 只需要使用delete这个命令即可完成所有的删除数据工作
2. delete删除数据时候, 只会删除最新版本的数据, 而deleteall 直接将对应数据的所有的历史版本全部删除
2.2.7.清空表
格式:truncate "表名"
流程: 先禁用表 ,然后删除表 ,最后创建表
2.2.8.如何删除表
格式: drop '表名'
ex: drop 'ORDER_INFO'
notes!!!
在删除表的时候, 一定要先禁用这个表, 否则无法删除
禁用表语法: disable '表名'
启动表语法: enable '表名'
2.2.9.如何一次性执行多条hbase的命令
操作:
1) 将hbase命令放置到一个文本文件中
2) 将这个文本文件上传到Linux目录下
3) 使用: hbase shell 文本文件路径 即可将命令进行执行操作
如何查看表中有多少条数据:
第一种方式: 使用 count 命令 适合于查看数量较少的表 当数据量比较大的时候, 此种效率效率比较低
第二种方式: 使用hbase提供的MR程序 来进行统计计数
格式: hbase org.apache.hadoop.hbase.mapreduce.RowCounter '表名'
2.2.10.扫描查询
#格式一:
scan '表名'
#格式二:
scan '表名', {LIMIT => N, COLUMNS => '列族:列名', FORMATTER =>'toString'}
#格式三:
scan '表名', {LIMIT => N, COLUMNS => ['列族:列名' , '列族:列名'...] , FORMATTER => 'toString'}
#格式四:
scan '表名', {LIMIT => N, COLUMNS => ['列族' , '列族:列名' ...] , FORMATTER => 'toString'}
ex1: scan 'ORDER_INFO' , {FORMATTER => 'toString'}
ex2: scan 'ORDER_INFO', {LIMIT => 3, COLUMNS => ['C1:STATUS','C1:PAYWAY'], FORMATTER => 'toString'}
ex3: scan 'ORDER_INFO', {LIMIT => 3, COLUMNS => ['C1'], FORMATTER =>'toString'}
2.2.11.高级的shell命令
#describe : 查看表的信息
格式: describe '表名'
#exists: 判断某个表是否存在
格式: exists '表名'
#is_enabled、is_disabled: 判断某个表是否是启动状态 还是禁止状态
格式:
is_enabled '表名'
is_disabled '表名'
#alter : 修改表结构信息
#新增列族:
alter 'USER_INFO', 'C3'
# 删除列蔟C3
alter 'USER_INFO', 'delete' => 'C3'
2.3.过滤器
-
过滤器的使用格式:
scan '表名', { FILTER => "过滤器(比较运算符, '比较器表达式')"
-
hbase中常用过滤器:
- rowkey过滤器:
- RowFilter : 实现行键字符串的比较和过滤
- PrefixFilter : rowkey前缀过滤器
- 列族过滤器 :
- FamilyFilter : 列簇过滤器
- 列名过滤器:
- QualifierFilter : 列标识过滤器,只显示对应列名的数据
- 列值过滤器:
- ValueFilter: 值过滤器,找到符合值条件的键值对
- SingleColumnValueFilter : 在指定的列族和列中进行比较的值过滤器
- SingleColumnValueExcludeFilter : 在指定的列族和列中进行比较的值过滤器 (排除匹配成功的值)
- 其他过滤器:
- PageFilter : 用于实现分页查询的操作
- 比较运算符 : > , < , >= , <= , != , =
- 比较器:
BinaryComparator 匹配完整字节数组
BinaryPrefixComparator 匹配字节数组前缀
NullComparator 匹配空值
SubstringComparator 模糊(包含)匹配子字符串 - 比较器表达式(比较器的使用方式):
BinaryComparator binary:值
BinaryPrefixComparator binaryprefix:值
NullComparator null
SubstringComparator substring:值
- rowkey过滤器:
2.4.HBase的高可用
- Base的高可用配置其实就是HMaster的高可用。要搭建HBase的高可用,只需要再选择一个节点作为HMaster,在HBase的conf目录下创建文件backup-masters,然后再backup-masters添加备份Master的记录。一条记录代表一个backup master,可以在文件配置多个记录
2.4.1.HBase的基础架构
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-94zHMUJ4-1608717200162)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1608090780241.png)]
-
主节点 Master Server(单节点,一主一备,一主多备)
功能:
- 管理从节点 RegionServer(主要)
- 分配region(主要)
- 在空闲时间进行数据的负载均衡
- 通过Zookeeper发布自己的位置给客户端
- 处理元数据的变更
-
从节点RegionSerevr(可以有多个)
RegionServer中包含了大量丰富的组件
- HFlie(StoreFile)
- Store
- MenStore
- Region
功能:
-
处理分配给他的Region(主要)
-
实现数据的读写操作
-
和主节点通信
一个HRegionServer下有一个HLog 和 多个Region组成 一个region下面有多个store模块组成 一个store模块一个memstore和多个storeFile(Hfile)组成
-
Store
功能:Region按列族垂直划分为[Store],存储到HDFS的文件中
-
MemStore
一个memstore默认大小是128M, 当数据存储达到128M, 将数据经过flush刷新到hdfs上, 形成一个storeFile文件,当storeFile达到一定阈值(10个)后, 将storeFile文件compact机制合并成一个大的File文件, 当HFile文件达到一定阈值(10Gb)后, 执行split分片机制, 一份为二;当HFile文件一分为二后, region进行一分为二操作, 每一个region管理大的HFile文件
-
zookeep
- 保证任何时候,集群中只有一个master
- 存贮所有Region的寻址入口
- 实时监控Region Server的状态,将Regionserver的上线和下线信息实时通知给Master
- 存储Hbase的schema,包括有哪些table,每个table有哪些column family
-
HLog:WAL预写日志
功能:当menstore数据丢失后,用于恢复内存中的数据
2.4.2.HBase基础架构实现图
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KXoJEP7Y-1608717200165)(D:\Documents\黑马大数据\Linux学习讲义\day24_实时部分_HBASE\图片\01-hbase的架构说明.png)]
2.4.3.HBase的读取数据的流程
-
由客户端发送读取数据的请求,先去连接zookeeper,主要目的是用于获取hbase:meta表所在的那个regionSerevr上
-
连接meta对应的regionServer,从meta表获取对应目标表有哪些region,以及这些region被哪些regionServer所管理
注意:
如果采用scan ;此时一般要返回整个表每个region对应regionServer的地址
如果采用get; 此时返回对应要读取rowkey所在region的regionServer的地址 -
并发 的连接对应regionServer,开始进行读取数据操作,首先先从menstore开始读取,读取完成后接着到blockche中读取,然后再到storeFile读取,最后再到大HFile中读取数据
注意: 在此处读取的时候, 如果命令中存在过滤器 此时就会将过滤条件分发到各个region上, 进行过滤读取操作
-
每个region可能都会有一定的数据返回, 将各个region读到数据都返回给客户端, 客户端对数据进行排序展示即可
hbase:meta表: 特殊的系统表, 此表只会有一个region 主要用于存储 hbase中各个表的元数据信息
元数据信息包含:
表对应有那些region, 每个region的范围是什么, 每个region被那些regionServer所管理 …
2.4.4.HBase的数据写入的流程
-
客户端发起写入数据的请求,首先会连接zookeeper,从zookeeper获取hbase:meta表对应Server的地址
-
连接meta表对应的regionServer,从meta表获取对应目标表有哪些region,以及从这些 region中根据插入的rowkey确认要插入到哪个region中,以及这个region的regionServer
-
连接对应的regionServer,开始准备写入数据
-
首先将数据写入这个regionServer的HLog的目录下,当这个目录写入成功以后,然后将数据写入到对应的region的对应的memstore中
服务器异步流程:
-
随着客户端不断的写入,那么menstore中数据变得越来越多,当menstore中数据达到一定的阈值(128M)后,就会启动flush刷新机制,将这份数据最终刷新到磁盘上形成一个storeFile的文件
-
随着不断的写入,不断的刷新,在磁盘(HDFS)上就会形成多个storeFile的文件,当这个storeFile的文件达到一定的阈值(3个及以上)后,开始启动compact机制,将多个storeFile的文件最终合并为一个大HFile文件
-
随着compact不断执行,大的HFile文件越来越大,当这个HFile达到一定的阈值(10GB)后,开始启动split机制,对大的HFile进行一分为二的操作,将一个HFile形成两个新的HFile,对应的region也会被分成两个region,每个region管理其中一个HFile的文件
2.4.4.1.flush刷新机制
-
目的:将内存中的数据刷新到磁盘(HDFS)上,形成一个小的HFile(storeFile)的过程
-
流程:hbase2.0及其以后的flush的流程
- 当memstore中数据写满后,首先关闭当前这个menstore,开启一个新的memstore
- 将原有这个以及关闭的memstore的数据放入到一个pipleline(管道队列)中
- 放入到pipleline管道后,此时数据变为只读(flush操作尽可能晚的执行)
- 有一个监控pipleline的管道的刷新线程,将这个管道中数据进行合并(in-memory-compact),合并为一份数据将数据刷新到HDFS上形成一个 storeFile的文件.
-
[]: https://blog.csdn.net/u010039929/article/details/74253093?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160825877316780257452887%252522%25252C%252522scm%252522%25253A%25252220140713.130102334.pc%25255Fall.%252522%25257D&request_id=160825877316780257452887&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-1-74253093.nonecase&utm_term=HBase%20%E7%9A%84%20flush%E5%88%B7%E6%96%B0%E6%9C%BA%E5%88%B6 “HBase Flush 解析”
2.4.4.2.compact合并机制
- 目的:将多个小HFile合并为 一个大的HFile的过程
- 整合并分为俩个阶段:
- minor
- 目的:将多个小HFile合并为一个较大的HFile的过程
- 流程:将每个小的HFile读取合并操作 ,整个过程对数据进行排序,如果里面有一些已经标识为删除或者过期的数据,在此阶段,不做任何处理,合并的过程都是采用追加的方式读取小 HFile数据,边将数据合并追加到一个新的HFile文件
- 注意:整个minor合并效率是比较高的
- major:默认7天执行一次,在生产中,一般major关闭自动执行,采用手动方式
- 目的:将这个较大的HFile和大的HFile进行合并操作,最终形成一个大的HFile的过程
- 流程:将这个较大的HFile和大的HFile进行合并操作,最终形成一个大的HFile过程
- 注意:此阶段对资源的消耗比较高,在执行major过程的时候,整个表表示不允许进行任何的读写操作;
- minor
2.5.HBase的命名空间
-
默认情况, hbase是有两个命名空间 : default 和 hbase
- hbase : hbase系统内部表所在的命名空间,主要有一个元数据表 meta 表
- default: hbase的默认命名空间, 用户在创建表的时候, 如果没有指定命名空间, 就会将表创建在命名空间下
-
命名空间作用:
- 对表进行分类管理, 一般情况下, 一个业务系统对应着一个库(命名空间)
- 对权限的管理
-
命名空间的相关的操作:
#创建命名空间: 语法:create_namespace 'MOMO_CHAT' #查看命名空间信息: 语法:list_namespace # 查看某一个命名空间信息: 语法:describe_namespace 'MOMO_CHAT' #删除命名空间: 语法:drop_namespace 'MOMO_CHAT' 注意:在删除命名空间的时候,在这个空间下,不能有表 #如何在某一个命名空间下创建表 语法:create 'MOMO_CHAT:MSG' , 'C1' 注意:如果要将数据创建在某一个命名空间下,在构件表的时候:命名空间名称:表名
2.6.数据压缩
2.6.1.压缩算法
-
HBase的数据的压缩算法选择:
-
GZIP的压缩率最高,但是其实CPU密集型的,对CPU的消耗比其他算法要多,压缩和解压速度也慢;
-
LZO的压缩率居中,比GZIP要低一些,但是压缩和解压速度明显要比GZIP快很多,其中解压速度快的更多;
-
Zippy/Snappy的压缩率最低,而压缩和解压速度要稍微比LZO要快一些
从压缩比: gzip压缩后的数据最小的, 但是压缩和解压的效率是最低的
LZO 在两者中间, 压缩比 要比 gzip 高差不多10% 左右 压缩和解压的效率要高于 gzip的;snappy: 拥有最高的解压缩的效率, 但是 压缩比当中最低的.
-
-
如何设置压缩语法:
#创建新表,并指定数据压缩算法 语法:create "MOMO_CHAT:MSG", {NAME => "C1", COMPRESSION => "GZ"} #修改已有的表,并指定数据压缩算法 语法:alter "MOMO_CHAT:MSG", {NAME => "C1", COMPRESSION => "GZ"}
2.6.2.HBase的预分区
-
默认情况下, 在hbase中创建一个表, 这个表只有一个region, 而一个region只能被一个regionServer所管理
-
那么在这种情况下,如果有大量的写入操作 以及大量的读取的操作, 都要去操作这张表, 而由于这个表只有一个region, 也就说只在一个regionserver上, 此时这个regionServer就会面临 高并发读写操作, 此时有可能导致服务器出现宕机的问题
-
如何实现预分区呢?
#方式一:手动预分区 语法:create 't1','f1',SQPLIT=>['10','20','30','40'] #方式二:指定分区数量,分区策略 语法:create 't2','f1',{NUMREGIONS=>15,SPLIALGO=>'HexStringSplit'} 当我们对一个表划分了多个region之后,至于region应该分配给那些regionserver,由 HMaster来决定,而HMaster在分配的会保证负载均衡的
2.6.3.HBase的rowkey设计原则
-
基础原则条件:
-
避免使用递增行键/时序数据
-
避免ROWKEY和列的长度过大:
注意:rowkey的长度 最大为 64kb 但是一般都用不了这么长,在实际生产中, 一般长度都在 10~100 区间, 在能满足情况下, 建议越短越好.
-
使用long等类型比String类型更省空间
-
ROWKEY唯一性: 所以一般情况下,我们会将时间戳放置在rowkey上
-
2.6.4.热点问题的解决
-
在整个表中, 有多个region, 其中有一个region非常的忙碌 而其他的region却很清闲, 此时认为 发生了热点问题
-
如何解决热点
- 反转策略: 比如说 手机号的反转
- 加盐策略 : 在rowkey前面添加随机数
- 哈希策略 : 类似于加盐操作, 但是当数据一致的时候, 加的盐也是相同的, 从而保证相关的数据放置在一起
2.6.4.1.反转策略
- 如果设计出的ROWKEY在数据分布上不均匀,但ROWKEY尾部的数据却呈现出了良好的随机性,可以考虑将ROWKEY的翻转,或者直接将尾部的bytes提前到ROWKEY的开头。
- 反转策略可以使ROWKEY随机分布,但是牺牲了ROWKEY的有序性
- 缺点:利于Get操作,但不利于Scan操作,因为数据在原ROWKEY上的自然顺序已经被打乱
2.6.4.2.加盐策略
- Salting(加盐)的原理是在原ROWKEY的前面添加固定长度的随机数,也就是给ROWKEY分配一个随机前缀使它和之间的ROWKEY的开头不同
- 随机数能保障数据在所有Regions间的负载均衡
- 缺点:因为添加的是随机数,基于原ROWKEY查询时无法知道随机数是什么,那样在查询的时候就需要去各个可能的Regions中查找,加盐对比读取是无力的
2.6.4.3.哈希策略
- 基于 ROWKEY的完整或部分数据进行 Hash,而后将Hashing后的值完整替换或部分替换原ROWKEY的前缀部分
- 这里说的 hash 包含 MD5、sha1、sha256 或 sha512 等算法
- 缺点:Hashing 也不利于 Scan,因为打乱了原RowKey的自然顺序
2.7.Phoenix的基本介绍
2.7.1.Phoenix
- Phoenix是一款基于 hbase的 可以通过 SQL的方式对hbase中数据进行CURD的操作, 并且Phoenix提供了完备的ACID事务支持,同时Phoenix 可以对hbase表中 各个列 构建索引信息, 从而加快对hbase的数据读写操.
2.7.2.Phoenix的使用操作
-
构建表
#建表语法: ##1.普通建表 create table if not exists 表名 ( rowkey名称 数据类型 primary key 列蔟名.列名1 数据类型 NOT NULL, 列蔟名.列名2 数据类型 NOT NULL, 蔟名.列名3 数据类型 ); ##2.hash加盐 drop table if exists ORDER_DTL; create table if not exists ORDER_DTL( "id" varchar primary key, C1."status" varchar, C1."money" float, C1."pay_way" integer, C1."user_id" varchar, C1."operation_time" varchar, C1."category" varchar ) COMPRESSION='GZ', SALT_BUCKETS=10; #注意事项: 采用Phoenix的hash加盐方式, 在hbase中对应表的rowkey前缀上会添加随机数据 从而在一定的程度上避免数据倾斜问题 如果使用Phoenix查询, 此时Phoenix会自动将前缀处理掉, 从而让无法感知到不到此操作, 提升体验度 #注意: 1) Phoenix 默认 会将所有小写变为大写的操作 如果非要使用小写, 请在需要使用小写的字段上添加 双引号 如果在建表的时候, 使用了小写, 后续只要涉及到这个小写的字段, 都必须添加双引号 所以,在实际使用中, 建议都设置为大写 2) Phoenix 尽能执行一些简单 基础的 查询工作, 复杂工作无法胜任(比如子查询 join操作)一般都是进行基础的单表操作 #他的操作: !table : 查看 Phoenix所有的表 !desc 表名 : 查看某个表的结构信息 drop table if exists 表名 : 删除表的操作 #插入数据: upsert into 表名(列蔟列名, xxxx, ) VALUES(XXX, XXX, XXX) #查询的操作: select * from 表 where .... #执行分页查询: select * from order_dtl limit 每页展示多少条 offset 从第几条开始查询; offset后的值 计算规则: (当前页 -1) * 每页展示条数
-
Phoenix与HBase之间产生映射配置操作
--建立视图 #映射HBase中的表 (重要) CREATE VIEW "my_hbase_table" ( k VARCHAR primary key, "v" UNSIGNED_LONG) default_column_family='a'; #映射Phoenix中的表 CREATE VIEW my_view ( new_col SMALLINT ) AS SELECT * FROM my_table WHERE k = 100; #映射到一个SQL查询 CREATE VIEW my_view_on_view AS SELECT * FROM my_view WHERE new_col > 70;
2.8.Phoenix的索引相关使用
-
全局索引
全局索引适用于读多写少业务 因为: 全局索引在构建的时候, 需要单独构建一张索引表, 此表和目标表具有相同region的数量当对目标表数据进行更新操作(增 删 改)的时候, 对应索引表也需要进行更新操作, 此时写入操作 就需要多干活, 效率自然就会降低 #创建全局索引 语法:CREATE INDEX 索引名称 ON 表名 (列名1, 列名2, 列名3...) #注意事项 SELECT查询中引用了其他非索引列,该索引是不会生效的 例如: 表A 中 有字段 B C D 三个字段 , 对C 进行构建索引的操作: select C from A where C =''; 此时 C索引会生效的 如果: select * from A where C = ''and B ='' ; 此时 C索引无法生效
-
本地索引
本地索引适合写操作频繁,读相对少的业务 因为: 本地索引在建立索引数据的时候, 直接在目标表内部构建, 此时不需要在额外构建一张索引表, 这个时候, 写入的时候, 不需要写入多个表, 本质上依然在写入一个表, 此时对写入没有太大的影响, 但是由于数据都在一块, 导致在内存中存储的数据量下降了,数据都存储在磁盘, 读取就会受到一定的影响. #注意事项 只要在查询中有本地索引的字段,就会使用,即使整个查询中有非索引字段也不受任何影响,如果目标表采用加盐的方式构建预分区表, 无法使用本地索引 #构建本地索引 CREATE INDEX my_index ON my_table (v1,v2) INCLUDE(v3)
-
函数索引
针对某个函数来构建索引操作, 当查询的时候, 使用这个函数 那么就会使用到对应索引信息 #构建覆盖索引 CREATE INDEX UPPER_NAME_IDX ON EMP (UPPER(FIRST_NAME||''||LAST_NAME)) #以下查询会走索引 SELECT EMP_ID FROM EMP WHERE UPPER(FIRST_NAME||' '||LAST_NAME)='JOHN DOE'
-
覆盖索引
当我们构建覆盖索引后,将原有的数据和索引的数据,放置在一起,形成一个单独的索引表, 这样在查询数据的时候,不需要在索引表查询到结果后然后再根据结果到目标中查询数据了 #构建覆盖索引 CREATE INDEX my_index ON my_table (v1,v2) INCLUDE(v3)
-
索引优化(全局+覆盖索引)–常用
#`语法 create index GBL_IDX_ORDER_DTL on ORDER_DTL(C1."user_id") INCLUDE("id", C1."money");
3.0.ELK(日志协议栈(elastic stack))
- elasticSearch:数据的存储和数据查询
- logstach:主要是用于进行数据的传递和采集工作:将数据从一个地方搬运到另一个地方去
- Kibana:主要是用于图标报表展示以及数据搜索
- Beats:主要是用于进行数据的写入工作
3.1.elastiSearch基本介绍
- elasticSearch:是一款基于java语言开发,主要用于进行全文检索的搜索引擎,底层是基于Lucene
- elasticSearch:分布式的集群架构,可以用于存储海量的数据,可以在海量前进行搜索处理工作
- 与solr比较:solr单独纯粹做查询的效率高于ES,如果写入的频次和读取的频次都比较多,采用ES的效率高于Solr
3.2.Lucene的基本介绍
- lucence是Apache是旗下的开源项目 ,最初由卡大爷开发的,luncene本质上是一个支持全文检索工具包(就是一坨jar包),并不是一个 完整搜索引擎但是可以通过lucene来构建一款完整的搜索引擎,最杰出的代表:solr | ElasticSearch
3.3.关系型数据库作为搜索的弊端
- 关系型数据库仅能进行首尾的模糊匹配操作,无法做到更加精确的查询
- 当用户输入错误的时候,查询的结果合用户期望的结果 完全不符合
- 随着数据量不断的提升,like模糊查询的效率也会变得越来越低
3.4.倒排索引
- 倒排索引的过程:
- 构建 一张索引库,对需要进行查询的数据进行粉刺鼻处理工作
- 当用户查询的时候,首先将用户的关键词进行分词,然后到索引库中根据分词后的数据,寻找相关的列表信息
- 根据结果内容,到原始数据下查询对应的内容即可
- 什么查询效率最高:基于主键的查询效最高;
- 整个倒排索引最难点就是如何粉分词的过程
3.5.ES的架构:主从分布式集群架构
-
主节点:
- 管理各个从节点状态信息
- 用于对索引库的CURD操作
- 用于存储索引库的元数据信息
- 负责数据的存储和读写操作
-
从节点:
- 负责数据的存储和读写操作
-
在一个分片的多个副本之间依然存在主从架构
- 主节点:负责数据的读写操作
- 从节点:负责数据的读操作
-
ES中的相关术语
-
index:索引库 在一个ES中可以构建多个索引库,理解为MYSQL中的数据库,或者hbase中命名空间
-
type:类型 在一个索引库下可以构建多个类型,相当于在MYSQL中 一个 数据库下面可以构建多个表,或者在命名空间下构建多个
-
field:字段 在索引库中,可以有多个字段,同时每个字段拥有数据类型的,类似于表中的多个字段,每个 字段有自己的类型
-
doucment:文档描述的是索引库中的一行数据,一个文档就表示一行数据,类型与 表中row
-
mapping: 映射 用于设置索引库中的字段的数据类型,比如说 ,字段采用什么类型,字段是否需要分词,是否需要索引
-
setting: 设置 用于对索引库设置比如:设置索引库有多少分片 多少个副本…
-
node: 节点 ES的各个 节点
-
shards: 分片 一个 索引库可以被分为多个分片 默认为5
-
replicas:副本 一个 分片可以被分为多个副本 默认为2
-
注意 :
- 分片的数量不受节点的限制
- 副本 的数据最多和节点的数量是一致的:副本数量<=节点的数量 副本一般为:2或者3
-
建 一张索引库,对需要进行查询的数据进行粉刺鼻处理工作
2. 当用户查询的时候,首先将用户的关键词进行分词,然后到索引库中根据分词后的数据,寻找相关的列表信息
3. 根据结果内容,到原始数据下查询对应的内容即可
- 什么查询效率最高:基于主键的查询效最高;
- 整个倒排索引最难点就是如何粉分词的过程
3.5.ES的架构:主从分布式集群架构
-
主节点:
- 管理各个从节点状态信息
- 用于对索引库的CURD操作
- 用于存储索引库的元数据信息
- 负责数据的存储和读写操作
-
从节点:
- 负责数据的存储和读写操作
-
在一个分片的多个副本之间依然存在主从架构
- 主节点:负责数据的读写操作
- 从节点:负责数据的读操作
-
ES中的相关术语
-
index:索引库 在一个ES中可以构建多个索引库,理解为MYSQL中的数据库,或者hbase中命名空间
-
type:类型 在一个索引库下可以构建多个类型,相当于在MYSQL中 一个 数据库下面可以构建多个表,或者在命名空间下构建多个
-
field:字段 在索引库中,可以有多个字段,同时每个字段拥有数据类型的,类似于表中的多个字段,每个 字段有自己的类型
-
doucment:文档描述的是索引库中的一行数据,一个文档就表示一行数据,类型与 表中row
-
mapping: 映射 用于设置索引库中的字段的数据类型,比如说 ,字段采用什么类型,字段是否需要分词,是否需要索引
-
setting: 设置 用于对索引库设置比如:设置索引库有多少分片 多少个副本…
-
node: 节点 ES的各个 节点
-
shards: 分片 一个 索引库可以被分为多个分片 默认为5
-
replicas:副本 一个 分片可以被分为多个副本 默认为2
-
注意 :
- 分片的数量不受节点的限制
- 副本 的数据最多和节点的数量是一致的:副本数量<=节点的数量 副本一般为:2或者3
-