分布式NoSQL数据库HBase实践与原理剖析(二)

news2024/11/30 0:48:56

title: HBase系列


第五章 HBase核心原理

5.1 系统架构

在这里插入图片描述

注意,其实上图中的HLog应该在HRegionServer里面,而不是在HRegion里面。所以图有点点问题。其实通过后面的物理存储的图也能发现这个问题。

Client 职责

1、HBase 有两张特殊表:
.meta.:记录了用户表的 Region 信息,.META.可以有多个 regoin 
-root-:记录了.META.表的 Region 信息,-ROOT-只有一个 region 。注意,0.98版本之后就没这个表了。

2、Client 访问用户数据前需要首先访问 zookeeper,找到-root-表的 region 所在的位置,然后 访问-root-表,接着访问.meta.表,最后才能找到用户数据的位置去访问,中间需要多次网络操作,不过 client 端会做 cache 缓存。
以上是老版本。

下面是新版本(098版本以后)
1、HBase 有一张特殊表:
.meta.:记录了用户表的 Region 信息

2、Client 访问用户数据前需要首先访问 zookeeper,找到.meta.表的 region 所在的位置,然后 访问.meta.表,才能找到用户数据的位置去访问,中间需要多次网络操作,不过 client 端会做 cache 缓存。

ZooKeeper 职责

老版本:
1、ZooKeeper 为 HBase 提供 Failover 机制,选举 master,避免单点 master 单点故障问题 
2、存贮所有 Region 的寻址入口:-root-表在哪台服务器上。-root-这张表的位置信息 
3、实时监控 RegionServer 的状态,将 RegionServer 的上线和下线信息实时通知给 Master 
4、存储 HBase 的 schema,包括有哪些 table,每个 table 有哪些 column family 

新版本:
1、ZooKeeper 为 HBase 提供 Failover 机制,选举 master,避免单点 master 单点故障问题 
2、存贮所有 Region 的寻址入口:.meta.表在哪台服务器上。.meta.这张表的位置信息 
3、实时监控 RegionServer 的状态,将 RegionServer 的上线和下线信息实时通知给 Master 
4、存储 HBase 的 schema,包括有哪些 table,每个 table 有哪些 column family 

Master 职责

1、为 RegionServer 分配 region 
2、负责 RegionServer 的负载均衡 
3、发现失效的 RegionServer 并重新分配其上的 region 
4、HDFS 上的垃圾文件(hbase)回收 
5、处理 schema 更新请求(表的创建,删除,修改,列簇的增加等等) 

RegionServer 职责

1、RegionServer 维护 Master 分配给它的 region,处理对这些 region 的 IO 请求 
2、RegionServer 负责 Split 在运行过程中变得过大的 region 。 负责 Compact 操作 

可以看到,client 访问 hbase 上数据的过程并不需要 master 参与(寻址访问 zookeeper 和 RegioneServer,数据读写访问 RegioneServer), master 仅仅维护者 table 和 region 的元数据 信息,负载很低。

.meta. 存的是所有的 region 的位置信息,那么 RegioneServer 当中 region 在进行分裂之后 的新产生的 region,是由 master 来决定发到哪个 RegioneServer,这就意味着,只有 master 知道 new region 的位置信息,所以,由 master 来管理.meta.这个表当中的数据的 CRUD 

StoreFile

保存的是实际数据的物理文件,StoreFile 以 HFile(一种文件存储格式,类似于TextFile、ORC、Parquet等,都属于数据格式)的形式存储在 HDFS 上。每个 Store 会有一个或多个 StoreFile(HFile),数据在每个 StoreFile 中都是有序的。

MemStore

是写缓存,由于 HFile 中的数据要求是有序的,所以数据是先存储在 MemStore 中,排好顺序后,等到达刷写的条件的时候才会刷写形成 HFile 文件,每次刷写都会形成一个新的 HFile。 

WAL

数据要经 MemStore 排序后才能刷写到 HFile,但是将数据保存在内存中,可能会数据丢失,为了解决这个问题,数据会先写在一个叫做 Write Ahead Log 的文件中,然后再写入 MemStore 中。所以在系统出现故障时候,数据可以通过这个日志文件重建。

Store

Store是物理上的概念,对应逻辑上的概念列簇

HFile

HFile是一种文件存储格式,和TextFile、Parquet、ORC 一样,都属于存储格式。刷写出来的文件形成了StoreFile,以HFile这种格式进行存储。是一种比较特殊的存储格式,内部是以键值对的方式来进行存储的。

5.2 物理存储

5.2.1 整体物理结构

在这里插入图片描述

说明:

1、Table 中的所有行都按照 rowkey 的字典序排列。 

2、Table 在行的方向上分割为多个 HRegion。 

3、HRegion 按大小分割的(默认 10G),每个表一开始只有一个 HRegion,随着数据不断插入表, HRegion 不断增大,当增大到一个阀值的时候,HRegion 就会等分会两个新的 HRegion。当表中的行不断增多,就会有越来越多的 HRegion。

4、HRegion 是 HBase 中分布式存储和负载均衡的最小单元。最小单元就表示不同的 HRegion 可以分布在不同的 HRegion Server 上。但一个 HRegion 是不会拆分到多个 Server 上的。

5、HRegion 虽然是负载均衡的最小单元,但并不是物理存储的最小单元。事实上,HRegion 由一个或者多个 Store 组成,每个 Store 保存一个 Column Family。每个 Store 又由一个 memStore 和 0 至多个 StoreFile 组成 

5.2.2 StoreFile和HFile结构

​ StoreFile 以 HFile 格式保存在 HDFS 上,请看下图 Hfile 的数据组织格式:

在这里插入图片描述

​ 首先 HFile 文件是不定长的,长度固定的只有其中的两块:Trailer 和 FileInfo。正如图中所示 的,Trailer 中有指针指向其他数据块的起始点。
​ File Info 中记录了文件的一些 Meta 信息,例如:AVG_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY 等。

​ HFile 分为六个部分:
Data Block 段----保存表中的数据,这部分可以被压缩
Meta Block 段 (可选的)–保存用户自定义的 kv 对,可以被压缩。
File Info 段—–HFile 的元信息,不被压缩,用户也可以在这一部分添加自己的元信息。
Data Block Index 段–Data Block 的索引。每条索引的 key 是被索引的 block 的第一条记录的 key。
Meta Block Index 段 (可选的)–Meta Block 的索引。

Trailer 段–—这一段是定长的。保存了每一段的偏移量,读取一个 HFile 时,会首先 读取 Trailer, Trailer保存了每个段的起始位置(段的Magic Number用来做安全check),然后,DataBlock Index 会被读取到内存中,这样,当检索某个 key 时,不需要扫描整个 HFile,而只需从内存中找 到 key 所在的 block,通过一次磁盘 io 将整个 block 读取到内存中,再找到需要的 key。 DataBlock Index 采用 LRU 机制淘汰。
HFile 的 Data Block,Meta Block 通常采用压缩方式存储,压缩之后可以大大减少网络 IO 和磁盘 IO,随之而来的开销当然是需要花费 cpu 进行压缩和解压缩。
目标 Hfile 的压缩支持两种方式:Gzip,LZO。 Snappy

​ Data Index 和 Meta Index 块记录了每个 Data 块和 Meta 块的起始点。

​ Data Block 是 HBase I/O 的基本单元,为了提高效率,HRegionServer 中有基于 LRU 的 Block Cache 机制。每个 Data 块的大小可以在创建一个 Table 的时候通过参数指定,大号的 Block 有利于顺序 Scan,小号 Block 利于随机查询。 每个 Data 块除了开头的 Magic 以外就是一个 个 KeyValue 对拼接而成, Magic 内容就是一些随机数字,目的是防止数据损坏。

​ HFile 里面的每个 KeyValue 对就是一个简单的 byte 数组。但是这个 byte 数组里面包含了很 多项,并且有固定的结构。我们来看看里面的具体结构:

在这里插入图片描述

​ 开始是两个固定长度的数值,分别表示 Key 的长度和 Value 的长度。紧接着是 Key,开始是固定长度的数值,表示 RowKey 的长度,紧接着是 RowKey,然后是固定长度的数值,表示 Family 的长度,然后是 Family,接着是 Qualifier,然后是两个固定长度的数值,表示 Time Stamp 和 Key Type(Put/Delete)。 Value 部分没有这么复杂的结构,就是纯粹的二进制数据了。

5.2.3 MemStore和StoreFile

​ 一个 HRegion由多个 Store 组成,每个 Store 包含一个列族的所有数据

​ Store 包括位于内存的一个 memstore 和位于硬盘的多个 storefile 组成

​ 写操作先写入 memstore,当 memstore 中的数据量达到某个阈值,HRegionServer 启动 flushcache 进程写入 storefile,每次写入形成单独一个 Hfile

​ 当总 storefile 大小超过一定阈值后,会把当前的 region 分割成两个,并由 HMaster 分配给相 应的 region 服务器,实现负载均衡

​ 客户端找数据的时候,先在memstore 里面找,找不到再到storefile里面去找。

第六章 HBase读写流程

6.1 HBase写数据

6.1.1 理论大图

在这里插入图片描述

6.1.2 文字补充

1、client 先根据 rowkey 找到对应的 region 所在的 regionserver
2、client 向 regionserver 提交写请求
3、regionserver 找到目标 region
4、region 检查数据是否与 schema 一致
5、如果客户端没有指定版本,则获取当前系统时间作为数据版本
6、将更新写入 WAL log
7、将更新写入 Memstore
8、判断 Memstore 的是否需要 flush 为 Store 文件。

6.1.3 细节补充之MemStore Flush

在这里插入图片描述

补充说明:

刷写时机:

1、当一个 memstore 的大小达到了 hbase.hregion.memstore.flush.size(默认值 128M),它所在 region 的所有 memstore 都会刷写。
并且这是一个阻塞写,也就是在刷写的过程中,写线程阻塞。

2、当 region server 中 memstore 的总大小达到
java_heapsize * hbase.regionserver.global.memstore.size(默认值 0.4) * hbase.regionserver.global.memstore.size.lower.limit(默认值 0.95)的时候, 
region 会按照其所有 memstore 的大小顺序依次进行刷写。直到 RegionServer 中所有 memstore 的总大小减小到上述值以下。

再次当 region server 中 memstore 的总大小达到 java_heapsize*hbase.regionserver.global.memstore.size(默认值 0.4)时,会阻止继续往所有的 memstore 写数据。

其实就是两个缓冲阈值。

3、当达到了自动刷写的时间,也会触发 memstore flush。
自动刷新的时间间隔可以通过属性进行配置,属性为: hbase.regionserver.optionalcacheflushinterval(默认 1 小时)。

有一个很详细的默认的配置文件 hbase-default.xml 。默认配置都在这个里面。

6.2 HBase读数据

6.2.1 理论大图

在这里插入图片描述

6.2.2 文字补充

0、假如读取一条数据,get 'stu','1001'
1、客户端问ZooKeeper请求获取meta表的位置信息(若是老的版本会先请求获取-root-表,然后通过-root-表里面的数据获取到.meta.表的位置),然后进一步通过.meta.表里面的数据,得到目标数据所在的RegionServer(就是数据 所在的 region 的主机地址) 
2、联系 regionserver 查询目标数据 
3、regionserver 定位到目标数据所在的 region,发出查询请求 
4、region 先在 memstore 中查找,命中则返回 
5、如果在 memstore 中找不到 , 则在 storefile 中扫描( 可能会扫描到很多的 storefile----BloomFilter) 

(BloomFilter,**布隆过滤器:迅速判断一个元素是不是在一个庞大的集合内**,但是他有一个弱点:它有一定的误判率) 
(**误判率**:原本不存在这个集合中的元素,布隆过滤器有可能会判断说它存在,但是,如果布隆过滤器,判断说某一个元素不存在这个集合,那么该元素就一定不在该集合内)

6.2.3 细节补充读取的先后顺序

细节1:读数据是按照时间戳的顺序来读的,并不是按照我们平时所认为的先读内存,在读磁盘,这种常识思维来的。完全是按照时间戳的先后来读,如果磁盘中的数据比内存中的数据的时间戳新,那么读取的就是磁盘中的。

下面测试一下这个细节:

1、创建一下表先

hbase(main):005:0> create 'stu','info'
hbase(main):007:0> put 'stu','1001','info:name','zhangsan'
Took 0.2334 seconds
hbase(main):008:0> scan 'stu'
ROW                                         COLUMN+CELL
 1001                                       column=info:name, timestamp=2021-10-13T17:38:09.520, value=zhangsan                                                            
1 row(s)
Took 0.0984 seconds
hbase(main):009:0> 

2、去hdfs的查看一下

/hbase/data/default/stu/abc159c5d597a821fb6b20f29c6e7704/info
可以发现info这个列簇下面的没有数据

在这里插入图片描述

3、手动刷写到磁盘上

hbase(main):009:0> flush 'stu'
Took 0.4177 seconds
hbase(main):010:0> 

在这里插入图片描述

可以看到已经刷写成zhangsan了。

在这里插入图片描述

也可以通过命令看一下这个HFile格式的文件。自己上网百度命令。

4、在Linux窗口中给时间格式转化为时间戳的样式

[root@hadoop11 bin]# date -d "2021-10-13T17:38:09.220" +%s
1634117889
[root@hadoop11 bin]# 
上面的结果是秒
可以加上3个0 变成 毫秒

5、再次手动添加一条带有时间戳的数据,并且这个时间戳比前面一条数据小。

hbase(main):021:0> put 'stu','1001','info:name','lisi',1634117889000
Took 0.0094 seconds 
hbase(main):022:0> 

6、再次查询,发现数据的结果还是zhangsan

hbase(main):022:0> scan 'stu'
ROW                                         COLUMN+CELL
 1001                                       column=info:name, timestamp=2021-10-13T17:38:09.520, value=zhangsan                                                            
1 row(s)
Took 0.0301 seconds
hbase(main):023:0> 

在这里插入图片描述

这个时候zhangsan的数据在磁盘上,而lisi的数据在内存中,但是磁盘上面的数据的时间戳新。所以返回的是磁盘上面的数据。

6.3 HBase分分合合那些事

6.3.1 StoreFile Compaction合并

1、基本概念

我们知道,memstore每次刷写都会生成一个新的HFile,并且同一个字段的不同版本(timestamp)和不同类型(Put/Delete)有可能会分布在不同的 HFile 中,所以呀,在查询时候需要遍历所有的 HFile。那么为了减少 HFile 的个数,以及清理掉过期和删除的数据,会进行 StoreFile Compaction。这样显而易见效率会高。

2、Compaction 的分类

分别是 Minor Compaction 和 Major Compaction。

Minor Compaction(小合并)会将临近的若干个较小的 HFile 合并成一个较大的 HFile,但不会清理过期和删除的数据。其实就是:只选取一些小的、相邻的HFile将它们合并成一个更大的 HFile 。

Major Compaction (大合并)会将一个 Store 下的所有的 HFile 合并成一个大 HFile,并且会清理掉过期和删除的数据。换句话说:将一个Store下的所有 HFile 合并成一个大文件,并执行物理删除操作。

6.3.2 Region Split切分

1、基本概念

在默认的情况下,每个 Table 起初只有一个 Region(因为数据量小啊),随着数据的不断写入,Region 会自动进行拆分。刚拆分时,两个子 Region 都位于当前的 Region Server,考虑到负载均衡,HMaster 有可能会将某个 Region 转移给其他的 Region Server。

2、切分的时机

1、当某个region中的某个Store下所有StoreFile的总大小超过hbase.hregion.max.filesize 的时候,该 Region 就会进行拆分(0.94 版本之前)。

2、当某个 region 中的某个 Store 下所有 StoreFile 的总大小超过 Min(R^2 * "hbase.hregion.memstore.flush.size",hbase.hregion.max.filesize"),该 Region 就会进行拆分,其中 R 为当前 Region Server 中属于这个Table表的个数(0.94 版本之后)。

第七章 HBase补充性知识

7.1 Rowkey的设计

1、基本概念

在HBase中间,一条数据的唯一标识就是 RowKey,那么这条数据存储于哪个分区,取决于 RowKey 处于哪个一个预分区的区间内,设计 RowKey 的主要目的其实就是让数据均匀的分布于所有的region 中,这样的话,可以在一定程度上防止数据倾斜。
下面看看怎么设计行键比较合适

2、设计方法

1、Hash散列
对rowkey进行hash,这样传递过来的数据就可以随机了。

2、字符串反转
这样可以在一定程度上将 put 进来的顺序的值分散开。

3、加随机前缀
也是给顺序均匀分散开

7.2 内存优化

​ HBase 在操作过程中需要大量的内存开销,这是因为 Table表 是可以缓存在内存中的,一般会分配整个可用内存的 70%-80% 给 HBase 使用即可。但是不建议分配非常大的堆内存,了解java的小伙伴可能知道, GC 过程持续太久会导致 RegionServer 处于长期不可用状态,其实一般设置 20~50G 内存就可以了。这只是建议,仅供参考。

7.3 预先分区

7.3.1 概念

在HBase中间,每一个 region 维护着起始行 StartRow 与结束行 EndRow ,如果加入的数据符合某个 Region 维护的RowKey 范围,则该数据就交给这个 Region 维护。
依照这个原则,我们可以提前将数据所要投放的分区提前大致的规划好,从而提高 HBase 性能。

7.3.2 具体操作示例

1、创建表

hbase(main):023:0> create 'stu2','info',SPLITS =>['1000','2000','3000']
Created table stu2
Took 2.2349 seconds
=> Hbase::Table - stu2
hbase(main):024:0> 

注意,上面命令是创建有4个分区的表stu2 。

2、去页面中查看

在这里插入图片描述

3、往里面put数据看看

put 'stu2','1001','info:name','zhangsan'
put 'stu2','2001','info:name','lisi'
put 'stu2','3001','info:name','wangwu'
put 'stu2','0001','info:name','zhaoliu'

hbase(main):024:0> put 'stu2','1001','info:name','zhangsan'
Took 0.0816 seconds
hbase(main):025:0> put 'stu2','2001','info:name','lisi'
Took 0.0101 seconds
hbase(main):026:0> put 'stu2','3001','info:name','wangwu'
Took 0.0370 seconds
hbase(main):027:0> put 'stu2','0001','info:name','zhaoliu'
Took 0.0281 seconds

4、再次查看页面

分区的范围是 左闭右开

会发现WriteRequests里面分别在对应的Region里面有对应的一条数据。这就说明数据按照规则插入到对应的分区里面去了。

在这里插入图片描述



声明:
        文章中代码及相关语句为自己根据相应理解编写,文章中出现的相关图片为自己实践中的截图和相关技术对应的图片,若有相关异议,请联系删除。感谢。转载请注明出处,感谢。


By luoyepiaoxue2014

微博地址: http://weibo.com/luoyepiaoxue2014 点击打开链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/41350.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣 21. 合并两个有序链表 C语言实现

题目描述: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 题目链接 方法1:遍历 新建一个链表 newList 用于存放合并后的链表,设置一个指针指向该链表最后一个位置的 next&#xff0c…

77.【JavaWeb文件上传和邮件发送04】

JavaWeb(二十五)、文件上传1.准备工作2.实用类介绍3.思维导图:4.正戏开始5.完整代码(二十六)、邮箱发送1.邮箱发送的原理:2.服务器的原理3.下载两个jar包4.基本类:5.全部代码(二十七)、网站注册发送邮件实现(二十五)、文件上传 1.首先创建一个empty项目 2.配置project项目中的…

【JVM】jvm中的栈简介

jvm中的栈简介一、JVM体系结构二、栈是什么?三、栈的特性四、栈帧五、栈的运行原理5.1 运行原理5.2 代码示例5.2.1 方法的入栈和出栈5.2.2 没有捕获异常5.2.3 捕获异常六、栈帧的内部结构七、运行时数据区,哪些部分存在Error和GC?八、本文源码…

boot 创建 https

需要在配置文件中:加入 server:ssl:key-store: classpath:https.keystorekey-store-type: JKSkey-alias: tomcatkey-password: 123456key-store-password: 123456port: 8089 这样原本请求的http,就需要变成https,其他类似 RestController p…

深度学习入门(五十六)循环神经网络——循环神经网络RNN

深度学习入门(五十六)循环神经网络——循环神经网络RNN前言循环神经网络——循环神经网络RNN课件潜变量自回归模型循环神经网络使用循环神经网络的语言模型困惑度(perplexity)梯度裁剪更多的应用RNNs总结教材1 无隐状态的神经网络…

周赛总结--LeetCode单周赛321场 AcWing79场

1. LeetCode单周赛321场 1.1 找出中枢整数 1.1.1 原题链接:力扣https://leetcode.cn/problems/find-the-pivot-integer/ 1.1.2 解题思路: 1、先保存 1-n 的和sum; 2、从 1 开始枚举,判断前 i 项和 cmp 与 sum - cmp i 是否相等…

MySQL第二弹

目录​​​​​​​ 一、数据库基本操作 1、查看数据库信息 2、查看数据库中的表信息 3、显示数据表的结构(字段) 4、常见的数据类型 4.1 数值类型 4.2 日期和时间类型 4.3 字符串类型 二、SQL语言概述 1、SQL语言 2、SQL分类 2.1 DDL:数据定…

【强化学习论文合集】NeurIPS-2021 强化学习论文

强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现…

js——高阶函数、闭包、递归以及浅拷贝和深拷贝

目录 一、高阶函数 1、什么是高阶函数 2、把一个函数作为参数 3、return 返回的也是一个函数 二、闭包 1、闭包是什么 2、变量的作用域 3、案例 4、结果展示: 5、总结: 三、递归 1、什么是递归 2、案例一 3、分析 4、问题 5、栈溢出又是什…

【Unity Shader​】 屏幕后处理5.0:讨论双重模糊的Bloom

接上一篇基于高斯模糊的Bloom继续进行接下来的学习。 1 一些必要的思考* 1.1 关于高质量Bloom 前面提到了,Bloom对于游戏必不可少的效果之一,于是我们不仅仅要把Bloom效果实现出来,效果的质量好坏就更加是我们需要关注的点了。高质量泛光&a…

面试宝典之C++多态灵魂拷问

🧸🧸🧸各位大佬大家好,我是猪皮兄弟🧸🧸🧸 文章目录一、重载,隐藏/重定义,覆盖/重写二、多态的原理三、inline可以是虚函数吗四、静态成员函数可以是虚函数吗五、构造函…

海丝一号-中国-2020

2020年12月22日,由中国电科38所和天仪研究院联合研制的我国首颗商业SAR卫星“海丝一号”搭载长征八号运载火箭在文昌卫星发射中心成功发射。海丝一号历时一年完成研制,整星重量小于185kg,成像最高分辨率1m,可以全天时、全天候对陆…

章节5 文件与目录管理

5-Linux文件和目录管理 (Linux操作系统-2022的前面章节都为铺垫) 常见命令格式 Command Options Arguments 命令 选项 参数 rm -rf /* -一个字母或字母组合,此选项为短选项,–单词,此选项为长选项 Options选项&…

因果推断 | 双重差分法笔记补充

换了新的环境后,一直在适应(其实是一直被推着走),所以停更了笔记好久啦。这一周周末终于有点得空,当然也是因为疫情,哪里都不能去,哈哈,所以来冒个泡~ 整理了最近pre的作业&#xf…

ESP32-CAM初始篇:Arduino环境搭建-->实现局域网推流

ESP32-CAM初始篇:Arduino环境搭建–>实现局域网推流 入手产品:安信可科技:ESP32-CAM摄像头开发板: 相关产品特性请访问安信可ESP32-CAM官网:https://docs.ai-thinker.com/esp32-cam 第一步:下载Ardui…

基于51单片机数字频率计的设计

目录 前 言 1 第一章 总体设计方案 2 1.1 总设计框图 2 1.2 硬件设计分析 2 1.2.1 电源的设计 2 (4):LCD1602的指令说明及时序 10 (5): LCD1602的RAM地址映射及标准字库表 13 第二章 软件设计与分析 15 2.1…

谷粒商城十一商城系统及整合thymeleaf渲染商城首页

我们的商城系统本应该也是前后端分离的,就像后台管理系统那样,然而出于教学考虑,前后端分离的话就会屏蔽掉很多细节,所以我们进行服务端的页面渲染式开发(有点儿类似freemarker) 这些页面直接粘贴到微服务…

含论文基于JSP的零食销售商城【数据库设计、源码、开题报告】

数据库脚本下载地址: https://download.csdn.net/download/itrjxxs_com/86500759 主要使用技术 ServletJSPcssjsMysqlTomcat 功能介绍 (1)前台功能模块: 注册登陆:顾客可以通过填写注册信息成为会员,登陆后才能进行购物车的管…

汽车 Automotive > SOME/IP应用学习

目录 SOME/IP介绍 SOME/IP主要功能 SOME/IP协议 SOME/IP服务类型 SOME/IP-举例 SOME/IP各模块协议 SOME/IP-基础元件 SOME/IP-SoAD SOME/IP-SD协议 SOME/IP-SD举例 SOME/IP-TP协议 SOME/IP-TP举例 SOME/IP介绍 SOME/IP ( Scalable service-Oriented Middleware ove…

基于Android的JavaEE课设

目录 1 技术栈 2 android前端 2.1 概述 2.1.1 目录结构 2.1.2 代码分层 2.2 技术点 2.2.1 数据绑定 2.2.2 前后端数据交互 2.2.3 九宫格图片 2.2.4 未处理消息提醒 2.2.5 动画效果 2.2.6 实时聊天 2.2.7 文件上传 2.2.8 底部弹窗 2.2.9 其他 3 后端 3.1 概述 …