【Java知识点大全】(六)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云解析DNS-重点域名监控,免费拨测 20万次(价值200元)
简介: 【Java知识点大全】

🍊 分库分表

对于分库分表,目前主流的是ShardingSphere,起源于当当网内部的应用框架。

shardingJDBC定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。它使⽤客户端直连数据库,以 jar 包形式提供服务,⽆需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。

ShardingProxy定位为透明化的数据库代理端,提供封装了数据库⼆进制协议的服务端版本,⽤于完成对异构语⾔的⽀持。⽬前提供 MySQL 和 PostgreSQL 版本,它可以使⽤任何兼容 MySQL/PostgreSQL 协议的访问客⼾端。

ShardingJDBC只是客户端的一个工具包,可以理解为一个特殊的JDBC驱动包,所有分库分表逻辑均由业务方自己控制,所以他的功能相对灵活,支持的数据库也非常多,但是对业务侵入大,需要业务方自己定制所有的分库分表逻辑。而ShardingProxy是一个独立部署的服务,对业务方无侵入,业务方可以像用一个普通的MySQL服务一样进行数据交互,基本上感觉不到后端分库分表逻辑的存在,但是这也意味着功能会比较固定,能够支持的数据库也比较少。这两者各有优劣。

🎉 数据分片主要流程

📝 sql解析整体结构

📝 路由引擎

📝 改写引擎

📝 执行引擎

📝 归并引擎

📝 源码流程

🎉 分库分表的的分片算法

提供一个分片键和一个分片表达式来制定分片算法

📝 NoneShardingStrategy
  • 不分片。这种严格来说不算是一种分片策略了。只是ShardingSphere也提供了这么一个配置。
📝 InlineShardingStrategy

最常用的分片方式

  • 配置参数: inline.shardingColumn 分片键;inline.algorithmExpression 分片表达式
  • 实现方式: 按照分片表达式来进行分片。
📝 StandardShardingStrategy

只支持单分片键的标准分片策略。

  • 配置参数:standard.sharding-column 分片键;standard.precise-algorithm-class-name 精确分片算法类名;standard.range-algorithm-class-name 范围分片算法类名
  • 实现方式:shardingColumn指定分片算法。preciseAlgorithmClassName 指向一个实现了io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm接口的java类名,提供按照 = 或者 IN 逻辑的精确分片 示例:com.roy.shardingDemo.algorithm.MyPreciseShardingAlgorithm。rangeAlgorithmClassName 指向一个实现了 io.shardingsphere.api.algorithm.sharding.standard.RangeShardingAlgorithm接口的java类名,提供按照Between 条件进行的范围分片。示例:com.roy.shardingDemo.algorithm.MyRangeShardingAlgorithm
  • 说明: 其中精确分片算法是必须提供的,而范围分片算法则是可选的。
📝 ComplexShardingStrategy

支持多分片键的复杂分片策略。

  • 配置参数:complex.sharding-columns 分片键(多个); complex.algorithm-class-name 分片算法实现类。
  • 实现方式:shardingColumn指定多个分片列。algorithmClassName指向一个实现了org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm接口的java类名。提供按照多个分片列进行综合分片的算法。示例:com.roy.shardingDemo.algorithm.MyComplexKeysShardingAlgorithm
📝 HintShardingStrategy

不需要分片键的强制分片策略。这个分片策略,简单来理解就是说,他的分片键不再跟SQL语句相关联,而是用程序另行指定。对于一些复杂的情况,例如select count(*) from (select userid from t_user where userid in (1,3,5,7,9)) 这样的SQL语句,就没法通过SQL语句来指定一个分片键。这个时候就可以通过程序,给他另行执行一个分片键,例如在按userid奇偶分片的策略下,可以指定1作为分片键,然后自行指定他的分片策略。

  • 配置参数:hint.algorithm-class-name 分片算法实现类。
  • 实现方式:algorithmClassName指向一个实现了org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm接口的java类名。 示例:com.roy.shardingDemo.algorithm.MyHintShardingAlgorithm。在这个算法类中,同样是需要分片键的。而分片键的指定是通过HintManager.addDatabaseShardingValue方法(分库)和HintManager.addTableShardingValue(分表)来指定。使用时要注意,这个分片键是线程隔离的,只在当前线程有效,所以通常建议使用之后立即关闭,或者用try资源方式打开。

而Hint分片策略并没有完全按照SQL解析树来构建分片策略,是绕开了SQL解析的,所有对某些比较复杂的语句,Hint分片策略性能有可能会比较好(情况太多了,无法一一分析)。

但是要注意,Hint强制路由在使用时有非常多的限制:

– 不支持UNION SELECT * FROM t_order1 UNION SELECT * FROM t_order2 INSERT INTO tbl_name (col1, col2, …) SELECT col1, col2, … FROM tbl_name WHERE col3 = ?

– 不支持多层子查询 SELECT COUNT(*) FROM (SELECT * FROM t_order o WHERE o.id IN (SELECT id FROM t_order WHERE status = ?))

– 不支持函数计算。ShardingSphere只能通过SQL字面提取用于分片的值 SELECT * FROM t_order WHERE to_date(create_time, ‘yyyy-mm-dd’) = ‘2019-01-01’;

从这里也能看出,即便有了ShardingSphere框架,分库分表后对于SQL语句的支持依然是非常脆弱的。

🎉 分库分表带来的问题

1、分库分表,其实围绕的都是一个核心问题,就是单机数据库容量的问题。我们要了解,在面对这个问题时,解决方案是很多的,并不止分库分表这一种。但是ShardingSphere的这种分库分表,是希望在软件层面对硬件资源进行管理,从而便于对数据库的横向扩展,这无疑是成本很小的一种方式。

2、一般情况下,如果单机数据库容量撑不住了,应先从缓存技术着手降低对数据库的访问压力。如果缓存使用过后,数据库访问量还是非常大,可以考虑数据库读写分离策略。如果数据库压力依然非常大,且业务数据持续增长无法估量,最后才考虑分库分表,单表拆分数据应控制在1000万以内。

当然,随着互联网技术的不断发展,处理海量数据的选择也越来越多。在实际进行系统设计时,最好是用MySQL数据库只用来存储关系性较强的热点数据,而对海量数据采取另外的一些分布式存储产品。例如PostGreSQL、VoltDB甚至HBase、Hive、ES等这些大数据组件来存储。

3、从ShardingJDBC的分片算法中我们可以看到,由于SQL语句的功能实在太多太全面了,所以分库分表后,对SQL语句的支持,其实是步步为艰的,稍不小心,就会造成SQL语句不支持、业务数据混乱等很多很多问题。所以,实际使用时,我们会建议这个分库分表,能不用就尽量不要用。

如果要使用优先在OLTP场景下使用,优先解决大量数据下的查询速度问题。而在OLAP场景中,通常涉及到非常多复杂的SQL,分库分表的限制就会更加明显。当然,这也是ShardingSphere以后改进的一个方向。

4、如果确定要使用分库分表,就应该在系统设计之初开始对业务数据的耦合程度和使用情况进行考量,尽量控制业务SQL语句的使用范围,将数据库往简单的增删改查的数据存储层方向进行弱化。并首先详细规划垂直拆分的策略,使数据层架构清晰明了。而至于水平拆分,会给后期带来非常非常多的数据问题,所以应该谨慎、谨慎再谨慎。一般也就在日志表、操作记录表等很少的一些边缘场景才偶尔用用。

🍊 主从复制

🎉 主从复制(replication)的工作原理

1)主服务器(master)把数据更改记录到二进制日志(binlog)中。

2)从服务器(slave)把主服务器的二进制日志复制到自己的中继日志(relaylog)中。

3)从服务器重做中继日志中的日志,把更改数据到自己的数据库上,以达到数据的最终一致性。

复制的工作原理并不复杂,其实就是一个完全备份加上二进制日志备份的还原。不同的是这个二进制日志的还原操作基本上实时在进行中。这里特别需要注意的是,复制不是完全实时地进行同步,而是异步实时。这中间存在主从服务器之间的执行延时,如果主服务器的压力很大,则可能导致主从服务器延时较大。

🎉 主从复制bin log 日志有几种记录方式,说说各自的优缺点

Replication之所以能够工作,主要还是归结于binlog(binary log),所以在 Replication 模式下必须开启binlog功能。slave从masters 上增量获取 binlog 信息,并在本地应用日志中的变更操作,变更操作根据选择的格式类型写入binlog文件,目前支持三种格式:

statement-based Replication(SBR) :master将SQL statements语句写入binlog,slave 也将statements 复制到本地执行;简单而言,就是在 master 上执行的 SQL 变更语句,也同样在 slaves 上执行。SBR 模式是 MySQL 最早支持的类型,也是Replication默认类型。

row-based Replication(RBR): master将每行数据的变更信息写入binlog,每条 binlog 信息表示一行(row)数据的变更内容,对于 slaves 而言将会复制 binlog 信息,然后单条或者批量执行变更操作;

mix-format Replication:混合模式,在这种模式下,master将根据根据存储引擎、变更操作类型等,从SBR、RBR中来选择更合适的日志格式,默认为 SBR;具体选择那种格式,这取决于变更操作发生的存储引擎、statement 的类型以及特征,优先选择“数据一致性” 最好的方式(RBR),然后才兼顾性能,比如 statement 中含有 “不确定性” 方法或者批量变更,那么将选择RBR方式,其他的将选择 SBR 以减少binlog 的大小。我们建议使用mix方式。SBR 和 RBR 都有各自的优缺点,对于大部分用而言,mix 方式在兼顾数据完整性和性能方面是最佳的选择。

SBR的优点

  • 因为 binlog 中只写入了变更操作的statements,所以日志量将会很小;
  • 当使用 SQL 语句批量更新、删除数据时,只需要在 binlog 中记录 statement 即可,可以大大减少log文件对磁盘的使用
  • 当然这也意味着 slave 复制信息量也更少,以及通过binlog恢复数据更加快速;

SBR的缺点 :有些变更操作使用 SBR 方式会带来数据不一致的问题,一些结果具有不确定性的操作使用SBR将会引入数据不一致的问题。

  • statement 中如果使用了 UDF(User Defination Fuction),UDF 的计算结果可能依赖于SQL 执行的时机和系统变量,这可能在 slave 上执行的结果与 master 不同,此外如果使用了trigger,也会带来同样的问题;
  • statement 中如果使用了如下函数的(举例):UUID(),SYSDATE(),RAND() 等,不过NOW() 函数可以正确的被Replication(但在 UDF 或者触发器中则不行);这些函数的特点就是它们的值依赖于本地系统,RAND() 本身就是随机所以值是不确定的。如果 statement 中使用了上述函数,那么将会在日志中输出warning信息;
  • 对于 “INSERT … SELECT” 语句,SBR 将比 RBR 需要更多的行锁。(主要是为了保障数据一致性,需要同时锁定受影响的所有的行,而RBR则不必要);
  • 对于 InnoDB,使用 “AUTO_INCREMENT” 的 insert 语句,将会阻塞其他 “非冲突” 的INSERT。(因为AUTO_INCREMENT,为了避免并发导致的数据一致性问题,只能串行,但 RBR 则不需要);
  • 对于复杂的SQL语句,在 slaves 上仍然需要评估(解析)然后才能执行,而对于RBR,SQL 语句只需要直接更新相应的行数据即可;在 slave 上评估、执行 SQL 时可能会发生错误,这种错误会随着时间的推移而不断累加,数据一致性的问题或许会不断增加。

RBR的优点

  • 所有的变更操作,都可以被正确的Replication,这事最安全的方式;
  • 对于 “INSERT … SELECT”、包含 “AUTO_INCREMENT” 的 inserts、没有使用索引的UPDATE/DELETE,相对于SBR 将需要更少的行锁。(意味着并发能力更强);
    RBR的缺点
  • 最大的缺点:就是 RBR 需要更多的日志量。任何数据变更操作都将被写入log,受影响的每行都要写入日志,日志包含此行所有列的值(即使没有值变更的列);因此RBR 的日志条数和尺寸都将会远大于SBR,特别是在批量的 UPDATE/DELETE 时,可能会产生巨大的 log 量,反而对性能带来影响,尽管这确实保障了数据一致性,确导致Replication的效率较低;

🎉 主从复制有几种方式?

📝 异步复制

MySQL主从集群默认采用的是一种异步复制的机制。Master处理事务过程中,将其写入Binlog就会通知Dumpthread线程处理,然后完成事务的提交,不会关心是否成功发送到任意一个slave中。主服务在执行用户提交的事务后,写入binlog日志,然后就给客户端返回一个成功的响应了。而binlog会由一个dump线程异步发送给Slave从服务,由于这个发送binlog的过程是异步的。主服务在向客户端反馈执行结果时,是不知道binlog是否同步成功了的。这时候如果主服务宕机了,而从服务还没有备份到新执行的binlog,那就有可能会丢数据。

📝 半同步复制

半同步复制机制是一种介于异步复制和全同步复制之前的机制。主库在执行完客户端提交的事务后,并不是立即返回客户端响应,而是等待至少一个从库接收并写到relay log中,才会返回给客户端。MySQL在等待确认时,默认会等10秒,如果超过10秒没有收到ack,就会降级成为异步复制。

这种半同步复制相比异步复制,能够有效的提高数据的安全性。但是这种安全性也不是绝对的,他只保证事务提交后的binlog至少传输到了一个从库,并且并不保证从库应用这个事务的binlog是成功的。另一方面,半同步复制机制也会造成一定程度的延迟,这个延迟时间最少是一个TCP/IP请求往返的时间。整个服务的性能是会有所下降的。而当从服务出现问题时,主服务需要等待的时间就会更长,要等到从服务的服务恢复或者请求超时才能给用户响应。

Master 处理事务过程中,提交完事务后,必须等至少一个Slave 将收到的binlog写入relaylog返回ack 才能继续执行处理用户的事务。相关配置rpl_semi_sync_master_wait_point=AFTER_COMMIT【这里MySQL5.5并没有这个配置,MySQL5.7 为了解决半同步的问题而设置的】rpl_semi_sync_master_wait_for_slave_count=1 (最低必须收到多少个slave的ack)rpl_semi_sync_master_timeout=100(等待ack的超时时间)

半同步复制需要基于特定的扩展模块来实现。mysql从5.5版本开始,往上的版本都默认自带了这个模块。这个模块包含在mysql安装目录下的lib/plugin目录下的semisync_master.so和semisync_slave.so两个文件中。需要在主服务上安装semisync_master模块,在从服务上安装semisync_slave模块。

📝 增强半同步复制

增强半同步和半同步不同是,等待ACK时间不同rpl_semi_sync_master_wait_point=AFTER_SYNC(唯一区别)半同步的问题是因为等待ACK的点是Commit 之后,此时Master已经完成数据变更,用户已经可以看到最新数据,当Binlog 还未同步到Slave时,发生主从切换,那么此时从库是没有这个最新数据的,用户又看到老数据。增强半同步将等待ACK的点放在提交Commit 之前,此时数据还未被提交,外界看不到数据变更,此时如果发送主从切换,新库依然还是老数据,不存在数据不一致的问题。

🍊 读写分离

为了保证数据一致,通常会需要保证数据只在主服务上写,而从服务只进行数据读取。这个功能就是读写分离。mysql主从本身是无法提供读写分离的服务的,需要由业务自己来实现,这也是ShardingSphere的一个重要功能。

在MySQL主从架构中,是需要严格限制从服务的数据写入的,一旦从服务有数据写入,就会造成数据不一致。并且从服务在执行事务期间还很容易造成数据同步失败。如果需要限制用户写数据,我们可以在从服务中将read_only参数的值设为1( set global read_only=1; )。这样就可以限制用户写入数据。

read_only=1设置的只读模式,不会影响slave同步复制的功能。限定的是普通用户进行数据修改的操作,但不会限定具有super权限的用户的数据修改操作。

如果需要限定super权限的用户写数据,可以设置super_read_only=0。另外如果要想连super权限用户的写操作也禁止,就使用"flush tables with read lock;",这样设置也会阻止主从同步复制!

🎉 读写分离延时导致的数据不一致解决方案

📝 数据同步

主从数据同步方案,一般都是采用的异步方式同步给备库。

我们可以将其修改为同步方案,主从同步完成,主库上的写才能返回。

  • 业务系统发起写操作,数据写主库;
  • 写请求需要等待主从同步完成才能返回;
  • 数据读从库,主从同步完成就能读到最新数据。

缺点:主库写需要等待主从完成,写请求的时延将会增加,吞吐量将会降低

📝 中间件路由

写请求,中间件将会发到主库,同时记录一下此时写请求的 key(操作表加主键等);

读请求,如果此时 key 存在,将会路由到主库;

一定时间后(经验值),中间件认为主从同步完成,删除这个 key,后续读将会读从库。

缺点:系统架构增加了一个中间件,整体复杂度变高,业务开发也变得复杂,学习成本也比较高

📝 缓存路由

写请求发往主库,同时缓存记录操作的 key,缓存的失效时间设置为主从的延时;

读请求首先判断缓存是否存在:

  • 若存在,代表刚发生过写操作,读请求操作主库;
  • 若不存在,代表近期没发生写操作,读请求操作从库。

优缺点:成本较低,但是呢我们此时又引入一个缓存组件,所有读写之间就又多了一步缓存操作

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
6月前
|
IDE Java 开发工具
Java 基础篇必背综合知识点最新技术与实操应用全面总结指南
本总结梳理了Java 17+的核心知识点与新技术,涵盖基础概念(模块化系统、GraalVM)、数据类型(文本块、模式匹配)、流程控制(增强switch)、面向对象(Record类、密封类)、常用类库(Stream API、HttpClient)、实战案例(文件处理)、构建工具(Maven、Gradle)、测试框架(JUnit 5)、开发工具(IDE、Git)及云原生开发(Spring Boot 3、Docker)。通过理论结合实操,帮助开发者掌握Java最新特性并应用于项目中。代码示例丰富,建议配合实践加深理解。
165 4
|
5月前
|
Java 数据库连接 数据库
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
本文全面总结了Java核心知识点,涵盖基础语法、面向对象、集合框架、并发编程、网络编程及主流框架如Spring生态、MyBatis等,结合JVM原理与性能优化技巧,并通过一个学生信息管理系统的实战案例,帮助你快速掌握Java开发技能,适合Java学习与面试准备。
236 2
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
|
5月前
|
存储 Java 程序员
Java 基础知识点全面梳理包含核心要点及难点解析 Java 基础知识点
本文档系统梳理了Java基础知识点,涵盖核心特性、语法基础、面向对象编程、数组字符串、集合框架、异常处理及应用实例,帮助初学者全面掌握Java入门知识,提升编程实践能力。附示例代码下载链接。
205 0
|
5月前
|
Java 编译器 数据安全/隐私保护
Java 大学期末考试真题与答案 含知识点总结 重难点归纳及题库汇总 Java 期末备考资料
本文汇总了Java大学期末考试相关资料,包含真题与答案、知识点总结、重难点归纳及题库,涵盖Java基础、面向对象编程、异常处理、IO流等内容,并提供完整代码示例与技术方案,助你高效复习备考。
267 3
|
5月前
|
存储 缓存 安全
Java基础 - 知识点
Java基础知识点涵盖语言特性、面向对象与基本数据类型、缓存池机制、String类特性、参数传递、类型转换、继承、抽象类与接口区别、重写与重载、Object通用方法及关键字使用等核心内容,是掌握Java编程的重要基石。
|
6月前
|
存储 安全 Java
2025 年最新 40 个 Java 基础核心知识点全面梳理一文掌握 Java 基础关键概念
本文系统梳理了Java编程的40个核心知识点,涵盖基础语法、面向对象、集合框架、异常处理、多线程、IO流、反射机制等关键领域。重点包括:JVM运行原理、基本数据类型、封装/继承/多态三大特性、集合类对比(ArrayList vs LinkedList、HashMap vs TreeMap)、异常分类及处理方式、线程创建与同步机制、IO流体系结构以及反射的应用场景。这些基础知识是Java开发的根基,掌握后能为后续框架学习和项目开发奠定坚实基础。文中还提供了代码资源获取方式,方便读者进一步实践学习。
1675 2
|
6月前
|
并行计算 Java API
Java 入门循环结构基础知识点详解
摘要:本文介绍了Java现代循环技术的进阶应用,包括Stream API、响应式编程和模式匹配,展示了如何用Stream API替代传统循环进行声明式集合处理(如过滤、映射和并行计算),以及响应式编程在异步非阻塞场景下的优势。文章还通过电商订单处理系统的案例演示了这些技术的综合应用,并提供了性能优化建议,如合理使用并行处理和避免循环内对象创建。这些现代特性使Java代码更简洁、高效,更适合高并发和I/O密集型场景。
85 1
|
6月前
|
缓存 算法 NoSQL
校招 Java 面试高频常见知识点深度解析与实战案例详细分享
《2025校招Java面试核心指南》总结了Java技术栈的最新考点,涵盖基础语法、并发编程和云原生技术三大维度: 现代Java特性:重点解析Java 17密封类、Record类型及响应式Stream API,通过电商案例演示函数式数据处理 并发革命:对比传统线程池与Java 21虚拟线程,详解Reactor模式在秒杀系统中的应用及背压机制 云原生实践:提供Spring Boot容器化部署方案,分析Spring WebFlux响应式编程和Redis Cluster缓存策略。
157 0
|
6月前
|
算法 安全 Java
2025 校招必看:Java 开发面试核心知识点深度解析及最新笔面试题汇总
本文针对2025校招Java开发面试,系统梳理了Java基础、集合框架、多线程并发、JVM等核心知识点,并附带最新笔面试题。内容涵盖封装、继承、多态、异常处理、集合类使用、线程同步机制、JVM内存模型及垃圾回收算法等。同时深入探讨Spring、数据库(MySQL索引优化、Redis持久化)、分布式系统(CAP理论、分布式事务)等相关知识。通过理论结合实例解析,帮助考生全面掌握面试要点,提升实战能力,为成功拿下Offer奠定坚实基础。
649 3