Bootstrap

实时数据处理

实时数据处理

Part1.nosql数据库概念

1.1.nosql数据的基本介绍

​ nosql型数据库,也将其称为 非关系数据库,有区别去于关系型数据库,在非关系型数据库中,不存在表关系,大部分非关系型数据库不支持SQL查询,不支持复杂的查询方案,不支持多行事务部处理,仅支持单行事务处理.

优点:读写性能非常高,常常被用于 缓存操作

适用场景:

  1. 高并发的读写
  2. 海量数据读写
  3. 高可扩展性
  4. 速度快

常见的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 主从复制原理
  1. 当从数据库启动后,会向主数据库发送SYNC命令
  2. 主数据库接收到SYNC命令后开始在后台保存快照(RDB持久化),并将保存快照期间接收到的命令缓存下来.
  3. 快照完成后,Redis(Master)将快照文件和所有缓存的命令发送给从数据库
  4. Redis(Slave)接收到RDB和缓存命令时,会开始载入快照文件并执行接收到的缓存的命令
  5. 后续,每当主数据库接收到写命令时,就会将命令同步给从数据库。所以3和4只会在初始化的时候执行.
2.6.2 主从复制的应用场景
  • 实现读写分离,以提高服务器的读写能力(主节点负责写入,从节点负责读取操作)
  • 当单机Redis无法应付大量的读请求时(尤其是消耗资源的请求),就可以通过主从复制功能来建立多个从数据库节点,主数据库只进行写操作,从数据库负责读操作
  • 这种主从复制,比较适合用来处理读多写少的场景,而当单个主数据库不能满足需求时,就需要使用Redis 3.0后推出的集群功能.
2.6.3.哨兵模式
  • 哨兵模式主要用来解决主从复制架构中,主节点宕机后,无法切换某个节点成为主节点的问题

  • 通过在每个 节点上启动一个哨兵进程,使用哨兵一直监控这主节点,当主节点宕机后,由哨兵来选举一个节点成为主节点.

  • 思考题

    1. 主从架构 和 哨兵模式 是否能够对redis进行横向扩展?

      答:并不会,只是对redis的进行纵向扩展,提升redis的读取的性能

    2. 如果redis的数据库比较多, 已经超出主节点内存大小了, 如何解决呢?

      解决方案:

      ​ 1)提升服务的内存大小(并不是最终方案)

      ​ 2)利于大数据系统(分布式思想):

      ​ 使用多台机器共同完成数据的存储,构建redis的集群

2.6.4.redis 集群
  • 实现redis集群化的原因

    1. 主从复制不能实现高可用
    2. 数据量的考虑,现有服务器内存不能满足业务数据的需要时,单纯向服务器添加内存不能达到要求,此时需要考虑分布式需求,把数据分布到不同服务器上
    3. 网络流量需求,业务的流量已经超过服务器的网卡的上限值,可考虑使用分布式来进行分流
  • 常用的数据 分布式:

    • 顺序分布: 关系型数据库的设计
    • 哈希分布:
      • 哈希取模
      • 一致性哈希
      • 预设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:值

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的读取数据的流程
  1. 由客户端发送读取数据的请求,先去连接zookeeper,主要目的是用于获取hbase:meta表所在的那个regionSerevr上

  2. 连接meta对应的regionServer,从meta表获取对应目标表有哪些region,以及这些region被哪些regionServer所管理

    注意:
    如果采用scan ;此时一般要返回整个表每个region对应regionServer的地址
    如果采用get; 此时返回对应要读取rowkey所在region的regionServer的地址

  3. 并发 的连接对应regionServer,开始进行读取数据操作,首先先从menstore开始读取,读取完成后接着到blockche中读取,然后再到storeFile读取,最后再到大HFile中读取数据

    注意: 在此处读取的时候, 如果命令中存在过滤器 此时就会将过滤条件分发到各个region上, 进行过滤读取操作

  4. 每个region可能都会有一定的数据返回, 将各个region读到数据都返回给客户端, 客户端对数据进行排序展示即可

    hbase:meta表: 特殊的系统表, 此表只会有一个region 主要用于存储 hbase中各个表的元数据信息
    元数据信息包含:
    表对应有那些region, 每个region的范围是什么, 每个region被那些regionServer所管理 …

2.4.4.HBase的数据写入的流程
  1. 客户端发起写入数据的请求,首先会连接zookeeper,从zookeeper获取hbase:meta表对应Server的地址

  2. 连接meta表对应的regionServer,从meta表获取对应目标表有哪些region,以及从这些 region中根据插入的rowkey确认要插入到哪个region中,以及这个region的regionServer

  3. 连接对应的regionServer,开始准备写入数据

  4. 首先将数据写入这个regionServer的HLog的目录下,当这个目录写入成功以后,然后将数据写入到对应的region的对应的memstore中


    服务器异步流程:

  5. 随着客户端不断的写入,那么menstore中数据变得越来越多,当menstore中数据达到一定的阈值(128M)后,就会启动flush刷新机制,将这份数据最终刷新到磁盘上形成一个storeFile的文件

  6. 随着不断的写入,不断的刷新,在磁盘(HDFS)上就会形成多个storeFile的文件,当这个storeFile的文件达到一定的阈值(3个及以上)后,开始启动compact机制,将多个storeFile的文件最终合并为一个大HFile文件

  7. 随着compact不断执行,大的HFile文件越来越大,当这个HFile达到一定的阈值(10GB)后,开始启动split机制,对大的HFile进行一分为二的操作,将一个HFile形成两个新的HFile,对应的region也会被分成两个region,每个region管理其中一个HFile的文件

2.4.4.1.flush刷新机制
  • 目的:将内存中的数据刷新到磁盘(HDFS)上,形成一个小的HFile(storeFile)的过程

  • 流程:hbase2.0及其以后的flush的流程

    1. 当memstore中数据写满后,首先关闭当前这个menstore,开启一个新的memstore
    2. 将原有这个以及关闭的memstore的数据放入到一个pipleline(管道队列)中
    3. 放入到pipleline管道后,此时数据变为只读(flush操作尽可能晚的执行)
    4. 有一个监控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过程的时候,整个表表示不允许进行任何的读写操作;

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 * fromwhere ....
    #执行分页查询:
    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.倒排索引
  • 倒排索引的过程:
  1. 构建 一张索引库,对需要进行查询的数据进行粉刺鼻处理工作
  2. 当用户查询的时候,首先将用户的关键词进行分词,然后到索引库中根据分词后的数据,寻找相关的列表信息
  3. 根据结果内容,到原始数据下查询对应的内容即可
  • 什么查询效率最高:基于主键的查询效最高;
  • 整个倒排索引最难点就是如何粉分词的过程
3.5.ES的架构:主从分布式集群架构
  • 主节点:

    1. 管理各个从节点状态信息
    2. 用于对索引库的CURD操作
    3. 用于存储索引库的元数据信息
    4. 负责数据的存储和读写操作
  • 从节点:

    1. 负责数据的存储和读写操作
  • 在一个分片的多个副本之间依然存在主从架构

    • 主节点:负责数据的读写操作
    • 从节点:负责数据的读操作
  • 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的架构:主从分布式集群架构
  • 主节点:

    1. 管理各个从节点状态信息
    2. 用于对索引库的CURD操作
    3. 用于存储索引库的元数据信息
    4. 负责数据的存储和读写操作
  • 从节点:

    1. 负责数据的存储和读写操作
  • 在一个分片的多个副本之间依然存在主从架构

    • 主节点:负责数据的读写操作
    • 从节点:负责数据的读操作
  • ES中的相关术语

    • index:索引库 在一个ES中可以构建多个索引库,理解为MYSQL中的数据库,或者hbase中命名空间

    • type:类型 在一个索引库下可以构建多个类型,相当于在MYSQL中 一个 数据库下面可以构建多个表,或者在命名空间下构建多个

    • field:字段 在索引库中,可以有多个字段,同时每个字段拥有数据类型的,类似于表中的多个字段,每个 字段有自己的类型

    • doucment:文档描述的是索引库中的一行数据,一个文档就表示一行数据,类型与 表中row

    • mapping: 映射 用于设置索引库中的字段的数据类型,比如说 ,字段采用什么类型,字段是否需要分词,是否需要索引

    • setting: 设置 用于对索引库设置比如:设置索引库有多少分片 多少个副本…

    • node: 节点 ES的各个 节点

    • shards: 分片 一个 索引库可以被分为多个分片 默认为5

    • replicas:副本 一个 分片可以被分为多个副本 默认为2

    • 注意 :

      • 分片的数量不受节点的限制
      • 副本 的数据最多和节点的数量是一致的:副本数量<=节点的数量 副本一般为:2或者3
;