• 15-HBase的介绍、数据模型以及架构模型


    八、HBase

    🔖Day14-Hbase的入门及系统框架

    重点掌握

    1、掌握Hbase的数据存储结构
    2、掌握Hbase的访问方式
    3、掌握Hbase的系统架构

    理解内容

    1、Hbase的四维数据存储模型 -03
    2、Hbase0.96前后数据定位方式 -24~25

    8.1HBase的介绍

    8.1.1HBase简介

    1. 定义理解:

      • HBase(HadoopDatabase)是一个开源的非关系型的分布式数据库,运行于HDFS文件系统之上,可以容错地存储海量稀疏的数据。HBase是一个高可靠、高性能、面向列、可伸缩、实时读写的分布式数据库,主要用来存储非结构化半结构化的松散数据

      • 基于列式存储,适合大数据的实时查询。

      • 对于结构化和非结构化的理解

        • 结构化数据
          • 关系型数据库围绕表、列和数据类型——数据的形态使用严格的规则。遵守这些严格规则的数据称为结构化数据。
        • 非结构化数据
          • HBase 设计上没有严格形态的数据。数据记录可能包含不一致的列、不确定大小等。这种数据称为半结构化数据(semistructured data)
    2. HBase与其他组件的结合使用

      • 利用HDFS作为其文件存储系统
      • 利用Zookeeper作为其分布式系统服务
      • 利用MapReduce来处理HBase中的海量数据

      参考资料: Hbase简介与基本原理_奋斗吧,青年!的博客-CSDN博客_hbase原理

      image-20220627170752702

    8.1.2HBase优点

    1. 容量大

      • HBase单表可以有百亿行、百万列,数据矩阵横向和纵向两个维度所支持的数据量级都非常具有弹性
    2. 面向列

      • 面向列的存储和权限控制,并支持独立检索,可以动态增加列。即,可以单独对列进行各方面的操作列式存储,其数据在表中时按照某列存储的,这样在查询只需要少数的几个字段的时候,能大大减少读取的数量
      • 下图显示了列族在面向列的数据库:

      image-20220627171605246

    3. 多版本

      • HBase的每一个列的数据存储有多个version,比如住址列,可能有多个变更,所有该列可以有多个version
    4. 稀疏性

      • 为空的列并不占用存储空间,表可以设计的非常稀疏
      • 不必向关系型数据库那样需要预先知道所有的列然后进行null填充
    5. 拓展性:

      • 底层依赖HDFS,当磁盘空间不足的时候,只需要动态增加datanode节点服务(机器)就可以了
    6. 高可靠性:

      • WAL机制,保证数据写入的时候不会因为集群异常而导致写入数据丢失Replication机制,保证了在集群出现严重的问题时候,数据不会发生丢失或者损坏Hbase底层使用HDFS,本身也有备份。
    7. 高性能:

      • 底层的LSM数据结构和RowKey有序排列等架构上的独特设计,使得Hbase写入性能非常高。Region切分、主键索引、缓存机制使得Hbase在海量数据下具备一定的随机读取性能,该性能针对Rowkey的查询能够到达毫秒级别,LSM树,树形结构,最末端的子节点是以内存的方式进行存储的,内存中的小树会flush到磁盘中(当子节点达到一定阈值以后,会放到磁盘中,且存入的过程会进行实时merge成一个主节点,然后磁盘中的树定期会做merge操作,合并成一棵大树,以优化读性能。)
        LSM树的介绍:https://www.cnblogs.com/yanghuahui/p/3483754.html

    8.1.3 HBase应用

    Hbase是一种NoSQL数据库,这意味着它不像传统的RDBMS数据库那样支持SQL作为查询语言。Hbase是一种分布式存储的数据库,技术上来讲,它更像是分布式存储而不是分布式数据库,它缺少很多RDBMS系统的特性,比如列类型,辅助索引,触发器,和高级查询语言等待。那Hbase有什么特性呢?如下

    1. 适合用HBase的场景

      • 首先数据库量要足够多,如果有十亿及百亿行数据,那么Hbase是一个很好的选项,如果只有几百万行甚至不到的数据量,RDBMS是一个很好的选择。因为数据量小的话,真正能工作的机器量少,剩余的机器都处于空闲的状态
      • 其次,如果你不需要辅助索引,静态类型的列,事务等特性,一个已经用RDBMS的系统想要切换到Hbase,则需要重新设计系统。
      • 最后,保证硬件资源足够,每个HDFS集群在少于5个节点的时候,都不能表现的很好。因为HDFS默认的复制数量是3,再加上一个NameNode。
      • Hbase在单机环境也能运行,但是请在开发环境的时候使用。
    2. 实际应用场景

      • 存储业务数据:车辆GPS信息,司机点位信息,用户操作信息,设备访问信息。。。
      • 存储日志数据:架构监控数据(登录日志,中间件访问日志,推送日志,短信邮件发送记录。。。),业务操作日志信息
      • 存储业务附件:UDFS系统存储图像,视频,文档等附件信息

      不过在公司使用的时候,一般不使用原生的Hbase API,使用原生的API会导致访问不可监控,影响系统稳定性,以致于版本升级的不可控。

    3. Hbase和RDBMS的比较

      属性HbaseRDBMS
      数据类型只有字符串丰富的数据类型
      数据操作增删改查,不支持join各种各样的函数与表连接
      存储模式基于列式存储基于表结构和行式存储
      数据保护更新后仍然保留旧版本替换
      可伸缩性轻易增加节点需要中间层,牺牲性能
    4. 数据管控层(助于理解)

      image-20220627172203331

    8.2 HBase数据模型

    image-20220627172437980

    HBase 是一个稀疏的、分布式、持久、多维、排序的映射,它以行键(row key),列族(columnFamily),列名(Column Qualifier)和时间戳(timestamp)为索引。

    8.2.1 NameSpace 命名空间

    1. 定义理解
      • 命名空间是类十余关系数据库系统中的数据库的概念,他其实是表的逻辑分组,这种抽象为多租户相关功能奠定了基础
      • 为了保护我们的表,创建的一个更高层级的单位
      • 命名空间是可以管理维护的,可以创建、删除或者更改
    2. 两个特殊预定义的命名空间:
      • default :没有明确指定名称空间的表将会自动落入此名称空间
      • hbase :系统命名空间,用户包含HBase内部表

    8.2.2 Table 表

    1. 定义理解
      • 存储相同数据的一个逻辑单元
      • 表有多个行数据组成,行有很多列组成
      • HBase是一个半结构化的数据库,所以每一行的列都有可能是不同的

    8.2.3 RowKey 行键

    1. 定义理解
      • RowKey是用来检索记录的主键,是一行数据的唯一标识
      • RowKey(行键)可以是任意字符串(最大长度是64KB,实际应用中长度一般为 10-100bytes),RowKey以字节数组保存。
      • HBase按照列进行存储,所以我们查询数据的时候会看到很多RowKey相同的列
    2. RowKey排序规则
      • RowKey存储的时候默认是以字典序排序的

    8.2.4 Column Family 列族

    1. 定义理解
      • 列族在物理上包含了许多的列与列的值,每个列族都有一些存储的属性可配置
        • 例如是否使用缓存、压缩类型、存储版本等。在表中,每一行都有相同的列族,尽管有些列族什么东西也没存。
      • 可以理解为多个列的集合,方便队列进行查找和管理
      • 一个表的列族需要在创建之前就要声明(先创建表,后期再维护表),而且一般一个表中的列族数不要超过3个
    2. 列的存放原则
      • 将功能属性相近的列存放在同一个列族,而且同一个列族中的列存放在同一个Store中
    3. 列、列族和表之间的关系
      • 列属于列族,列族属于表,即 列-->列族-->表
      • 一个表中的列族是固定的,但是列族中的列是不固定的

    8.2.5 Column Qualifier

    1. 定义理解
      • 列族额限定词,理解为列的唯一标识。但是列标识是可以改变的,因此每一行可能有不同的列标识
      • 使用的时候必须 列族:列
      • 列可以根据需求动态添加或者删除,同一个表中不同行的数据列都可以不同

    8.2.6 TimeStamp

    1. 定义理解:
      • 默认数据版本就是时间戳,解决HDFS不能随时修改数据的弊端
      • 查询数据的时候默认显示最新的数据
    2. 版本回收方式
      • 为了避免数据存在过多版本中造成管理 (包括存贮和索引)负担,HBASE 提供了两种数据版本回收方式
        • 一是保存数据的最后n个版本
        • 二是保存最近一段时间内的版本(比如最近七天)

    8.2.7 Cell

    1. 定义理解:
      • Cell是由row,column family,column qualifier,version 组成的,所有的数据都是字符串
      • Cell中的数据是没有类型的,全部是字节码形式存贮。
        • 因为HDFS上的数据都是字节数组

    8.3 HBase高可用集群搭建

    8.3.1准备安装环境

    • [root@node01 ~]# tar -zxvf hbase-2.2.5-bin.tar.gz
    • [root@node01 ~]# mv hbase-2.2.5 /opt/yjx/
    • [root@node01 ~]# cd /opt/yjx/hbase-2.2.5/conf/

    8.3.2 修改集群环境

    • [root@node01 conf]# vim hbase-env.sh

      export HBASE_LOG_DIR=${HBASE_HOME}/logs
      export JAVA_HOME=/usr/java/jdk1.8.0_231-amd64
      export HBASE_MANAGES_ZK=false
      export HADOOP_HOME=/opt/yjx/hadoop-3.1.2/
      
      • 1
      • 2
      • 3
      • 4

    8.3.3修改配置文件

    • [root@node01 conf]# vim hbase-site.xml

      <!-- 31dd -->
      <!--设置HBase表数据,也就是真正的HBase数据在hdfs上的存储根目录-->
      <property>
      <name>hbase.rootdir</name>
      <value>hdfs://hdfs-yjx/hbase</value>
      </property>
      <!--是否为分布式模式部署,true表示分布式部署-->
      <property>
      <name>hbase.cluster.distributed</name>
      <value>true</value>
      </property>
      <!--zookeeper集群的URL配置,多个host中间用逗号-->
      <property>
      <name>hbase.zookeeper.quorum</name>
      <value>node01:2181,node02:2181,node03:2181</value>
      </property>
      <!--HBase在zookeeper上数据的根目录znode节点-->
      <property>
      <name>zookeeper.znode.parent</name>
      <value>/hbase</value>
      </property>
      <!-- 本地文件系统tmp目录,一般配置成local模式的设置一下,但是最好还是需要设置一下,因为很
      多文件都会默认设置成它下面的-->
      <property>
      <name>hbase.tmp.dir</name>
      <value>/var/yjx/hbase</value>
      </property>
      <!-- 使用本地文件系统设置为false,使用hdfs设置为true -->
      <property>
      <name>hbase.unsafe.stream.capability.enforce</name>
      <value>false</value>
      </property>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
    • vim regionservers

      node01
      node02
      node03
      
      • 1
      • 2
      • 3

    8.3.4 备用Master节点

    • [root@node01 conf]# vim backup-masters

      node02
      
      • 1

    8.3.5 拷贝Hadoop配置文件

    • [root@node01 conf]# cp /opt/yjx/hadoop-3.1.2/etc/hadoop/core-site.xml /opt/yjx/hbase-2.2.5/conf/
    • [root@node01 conf]# cp /opt/yjx/hadoop-3.1.2/etc/hadoop/hdfs-site.xml /opt/yjx/hbase-2.2.5/conf/

    8.3.6 拷贝分发软件

    • [root@node02 ~]# scp -r root@node01:/opt/yjx/hbase-2.2.5 /opt/yjx/
    • [root@node03 ~]# scp -r root@node01:/opt/yjx/hbase-2.2.5 /opt/yjx/

    8.3.7 修改环境变量

    • [root@node01 conf]# vim /etc/profile

      export HBASE_HOME=/opt/yjx/hbase-2.2.5
      export PATH=$HBASE_HOME/bin:$PATH
      
      • 1
      • 2
    • 拷贝到其他节点

      • [root@node01 conf]# scp /etc/profile root@node02:/etc/profile
      • [root@node01 conf]# scp /etc/profile root@node03:/etc/profile
    • 让配置文件生效

      • 【123】 source /etc/profile

    8.4.8 启动集群

    • 【123】 zkServer.sh start
    • [root@node01 conf]# start-all.sh
    • [root@node01 conf]# start-hbase.sh

    8.4.9 web页面验证

    1. 可以看到服务器1启动和HMaster 和 HRegionServer进程,服务器2和服务器3启动和HRegionServer进程。

    2. 查看HBase的集群情况:http://192.168.88.101:16010

      image-20220627162509751

    8.4 HBase访问方式

    8.4.1 HBase shell

    我们可以先用HBase提供的命令行工具,位于HBase的/bin/目录下

    1. 开启环境命令

      • 【123】zkServer.sh start
      • 【1】start-all.sh
      • 【1】start-hbase.sh
    2. 进入退出HBase

      • hbase shell
      • exit
    3. 关闭环境并关机命令

      • 【1】stop-hbase.sh
      • 【1】stop-all.sh
      • 【123】zkServer.sh stop
      • 【123】shutdown -h now
    4. 查看帮助信息

      • help
    5. 查询服务器状态

      • status
    6. 查询hbase版本

      • version

    1. Shell实现DDL操作

    1. 创建表

      • 语法:create ‘表名’ , {NAME => , VERSIONS => }
      • 例如:创建表t1,有两个family name:f1,f2,且版本数均为2
        • create ‘t1’,{NAME => ‘f1’, VERSIONS => 2},{NAME => ‘f2’, VERSIONS=> 2}
      • 非标准创建表的语法:创建表member,列族是member_id,address,info,版本为1
        • create ‘member’,‘member_id’,‘address’,‘info’
    2. 获得表的描述信息

      • 语法:
        • list ‘表名’
        • describe ’ 表名’
      • 例如
        • list :查看所有的表名称(列出所有的表)
        • describe ‘member’ :查看表的描述信息
    3. 删除一个列族

      • 语法 alter,disable,enable
        • alter
          • 我们之前建了3个列族,但是发现member_id这个列族是多余的,因为他就是主键,所以我们要将其删除
          • alter ‘member’,{NAME=>‘member_id’,METHOD=>‘delete’}
        • enable
          • 使表可用
          • enable ‘member’
        • disable
          • 禁用表
          • disable ‘member’
    4. drop一个表

      create 'temp_table','member_id','address','info'
      hbase(main):029:0>disable 'temp_table'
      hbase(main):030:0>drop 'temp_table'
      
      • 1
      • 2
      • 3
    5. 查询表是否存在

      exists 'member'
      
      • 1
    6. 判断表是否enable(启用)

      is_enabled 'member'
      
      • 1
    7. 判断表是否disable

      is_disabled 'member'
      
      • 1
    8. 查看文件存储路径

      hdfs dfs -ls /yjx/hbase/data/default/member

    9. truncate此命令将删除并重新创建一个表

      truncate ‘t1’

    10. 表的预分区

      # create table with specific split points
      hbase>create 'table1','f1',SPLITS => ['\x10\x00', '\x20\x00', '\x30\x00','\x40\x00']
      # create table with four regions based on random bytes keys
      hbase>create 'table2','f1', { NUMREGIONS => 8 , SPLITALGO => 'UniformSplit' }
      # create table with five regions based on hex keys
      hbase>create 'table3','f1', { NUMREGIONS => 10, SPLITALGO => 'HexStringSplit' }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    2.Shell实现DML操作

    3.Shell实现DQL操作

    4. Shell实现Region管理

    8.4.2 Java访问HBaseAPI

    8.5 HBase架构模型

    HBase有三个主要组成部分:客户端库,主服务器和区域服务器。

    image-20220627202736626

    8.5.1Client

    1. 主要功能
      • 客户端负责发送请求到数据库,客户端连接的方式有很多种
        • hbase shell
        • 类JDBC
      • client维护着一些cache来加快对hbase的访问,比如regione的位置信息。
    2. 发送请求的类型
      • DDL:数据库定义语言(表的建立,删除,添加删除列族,控制版本)
      • DML:数据库操作语言(增删改)
      • DQL:数据库查询语言(查询–全表扫描–基于主键–基于过滤器)

    8.5.2 HMaster

    1. 定义
      • HBase集群的主节点,HMaster也可以实现高可用(active–standby)
        • 通过Zookeeper来维护主副节点的切换
    2. 作用
      • 上下线的监督,创建表的时候为Region server分配region并负责Region server的负载均衡
      • 负责接受客户端对table的结构DDL(创建,删除,修改)操作,DML和DQL由其他节点承担
        • 因为HMaster没有联邦机制,业务承载能力有限,而且数据库的表结构很少会变化,大部分都是CRUD操作
        • 表的元数据信息–>Zookeeper上面
        • 表的数据–>HRegionServer上
      • 负责监督HRegionServer的健康状况
        • 当HRegionServer下线的时候,HMaster会将当前HRegionServer上的Region转移到其他的HRegionServer

    8.5.3 HRegionServer

    1. 定义

      • HBase的具体工作节点(RegionServer属于HBase具体数据的管理者),一般一台主机就是一个RegionServer
    2. 作用

      • 一个RegionServer中包含很多HMaster分配给RegionServer的Region,同时RegionServer处理这些Region的IO请求(DML和DQL请求)
      • 当客户端发送DML和DQL操作的时候,HRegionServer负责和客户端建立连接
      • HRegionServer会实时和HMaster保持心跳,汇报当前节点的信息
      • 当接收到Hmaster命令创建表的时候,分配一个Region对应一张表
      • Region server负责切分在运行过程中变得过大的region
    3. 其他:

      • 当意外关闭的时候,当前节点的Region会被其他HRegionServer管理
    4. 图解 RegionServer、Region、store和storefile之间的关系

      image-20220627204907757

    8.5.4 HRegion

    1. 定义理解
      • HRegion是HBase中分布式存储和负载均衡最小单元(HBase的表数据具体存放的位置)
        • 最小单元就表示不同的HRegion可以分布在不同的 HRegion server上。
      • 一个Region只属于一张表,但是一张表可以有多个Region
      • HBase自动把表水平划分成多个区域(region),每个region会保存一个表里面某段连续的数据
    2. Region的平分
      • 最开始声明表的时候就会为这个表默认创建一个Region,一个Region只属于一张表,随着时间的推移Region会越来越大 ,当达到阈值10G时,然后Region会1分为2(逻辑上平分,尽量保证数据的完整性)
        • 切分后的其中一个Region转移到其他的HRegionServer上管理
    3. 预分区
      • 当table中的行不断增多,就会有越来越多的region。这样一张完整的表被保存在多个Regionserver 上。
      • 为了防止前期数据的处理都集中在一个HRegionServer,我们可以根据自己的业务进行预分区

    8.5.5 Store

    1. 定义理解
      • 一个表中的一个列族对应一个Store
      • 一个Store里面分为1个MenStore和0或多个StoreFile
    2. HRegion、Store和columns family之间的关系
      • HRegion是表获取和分布的基本元素,由一个或者多个Store组成,每个store保存一个columns family。
    3. HFile
      • HFile是Hbase在HDFS中存储数据的格式,它包含多层的索引,这样在Hbase检索数据的时候就不用完全的加载整个文件。
      • StoreFile存储在HDFS上之后就称为HFile

    8.5.6 StoreFile

    1. 定义理解
      • StoreFile是文件的硬盘存储,直接存到HDFS上,存到HDFS之后被称为HFile
      • StoreFile是数据存储文件的映射,对应HDFS上的HFile
    2. 表、Region、Store、StoreFile之间的关系
      • 一个table对应多个Region,一个Region对应多个Store,一个Store对应一个MEMStore和多个StoreFile,多个StoreFile内部有序,但是外部无序
      • 集群会设置一些阈值,当达到阈值的时候开始将小文件合并成大文件

    8.5.7 MenStore

    1. 定义理解

      • MenStore是基于内存存放数据,每个Store大概分配128M的空间
      • HFile中并没有任何Block,数据首先存在于MemStore中。Flush发生时,创建HFile Writer
      • 数据最开始优先写入到MEMStore,当flush的时候才会被写入到磁盘中(之前在内存中)
      • 默认情况下,一个MemStore的大小为128M,当客户端向数据库插入数据的时候,当内存使用到128M的时候,直接申请128M的内存空间,数据直接写到新内存中,原来已经满的数据写出到HDFS上,称为HFile
    2. MenStore与 Data Block之间的关系

      • 当操作数据的时候,第一个空的Data Block初始化,初始化后的Data Block中为Header部分预留了空间,Header部分用来存放一个Data Block的元数据信息。
      • 位于MemStore中的KeyValues被一个个append到位于内存中的第一个Data Block中
        • 如果配置了Data Block Encoding,则会在Append KeyValue的时候进行同步编码,编码后的数据不再是单纯的KeyValue模式。
        • Data Block Encoding是HBase为了降低KeyValue结构性膨胀而提供的内部编码机制

    8.5.8 Hlog

    1. 定义理解

      • HBase的日志机制,WAL(Write After Log)做任何操作之前先写日志,一个HRegionServer只有一个Log文档
      • 日志也会存储到HDFS上,在任何操作之前先记录日志到HDFS,以后MenStore丢失数据或者RegionServer异常都能够通过日志进行恢复一个RegionServer对应的一个Hlog
      • HLog文件就是一个普通的Hadoop Sequence File,SequeceFile的Key是HLogKey对象
    2. 作用

      • 当memStore达到阈值的时候开始写出到文件之后,会在日志中对应的位置标识一个检查点
      • WAL记录所有的Hbase数据改变,如果一个RegionServer在MemStore进行FLush的时候挂掉了,WAL可以保证数据的改变被应用到。如果写WAL失败了,那么修改数据的完整操作就是失败的。
    3. 图解Hlog在整个HBase中的结构

      image-20220627224930391

    8.5.9 Zookeeper

    1. 定义理解
      • HBase的协调服务
    2. 作用
      • 主备选举与切换
      • 记录当前集群的状态信息,当主备切换的时候,集群的状态可以被新主节点直接读取到
      • 记录当前集群的数据存放信息
      • 存储HBase的元数据信息

    8.6 HBase读写流程

    8.6.1 公共流程(三层索引)

    1. 对于数据对应的Region位置在哪里的问题的提出
      • HBase中单表的数据量通常可以达到TB级或PB级,但大多数情况下数据读取可以做到毫秒级。HBase是如何做到的呢?要想实现表中数据的快速访问,通用的做法是数据保持有序并尽可能的将数据保存在内存里。HBase也是这样实现的
      • 对于海量级的数据,首先要解决存储的问题。数据存储上,HBase将表切分成小一点的数据单位region,托管到RegionServer上,和以前关系数据库分区表类似。但比关系数据库分区、分库易用。这一点在数据访问上,HBase对用户是透明的。数据表切分成多个Region,用户在访问数据时,如何找到该条数据对应的region呢?

    1. HBase 0.96以前

    1. 两个表-Root- .Meta.

      • 系统维护的两个特殊的表 -Root- .Meta. 用来查找各种表的region位置在哪里

      • -Root-和.Meta.也像HBase中其他表一样会切分成多个region

      • .Meta. 表

        • 存储了表对应Region对应的RegionServer RowKey的区间(目录)
        • 但是.Meta. 表也是一张普通的Hbase表,也需要存放到RegionServer中
      • -Root- 表

        • 专门用来记录 .meta.表的存放位置(目录的目录),通过-root-表就可以找到 .meta. 表的region位置
        • 它的机构和meta一模一样,但是它只维护meta表的切分信息
        • 理论上-root-表不会被切分(数据量),一般 -root- 表只需要一个Region即可(目录的目录,内容不会超过一个Region的10G大小),-root- 的Region信息存放在Zookeeper
    2. 用户访问表的流程

      • client–>Zookeeper --> .root. 表–>-meta-表–>RegionServer–>Region

      image-20220627232821584

    2.HBase 0.96以后

    1. -ROOT-表被移除,直接将.Meta表region位置信息存放在Zookeeper中。Meta表更名为hbase:meta,

    2. 查询流程

      Client—>Zookeeper—>HBase:meta—>用户表Region

  • 相关阅读:
    学习pytorch13 神经网络-搭建小实战&Sequential的使用
    【计算机毕业设计】病人跟踪治疗信息管理系统源码
    如何重装Windows Mirosoft Store
    后端接入层技术的一些思考
    什么是产品经理&&为什么说做好一款产品需要情怀?
    关于本地项目连接git远程仓库以及git设置ignore文件
    为什么嵌入通常优于TF-IDF:探索NLP的力量
    电商直播增加人气,留人技巧有哪些
    医院检验LIS系统源码
    HTTPS、SSL/TLS,HTTPS运行过程,RSA加密算法,AES加密算法
  • 原文地址:https://blog.csdn.net/weixin_50627985/article/details/125493908