HTTP和HTTPS的区别
ssL(Security Sockets Layer,安全套接层)
>为网络通信提供安全及数据完整性的一种安全协议
>是操作系统对外的API,SSL3.0后更名为TLS
>采用身份验证和数据加密保证网络通信的安全和数据的完整性>HTTPS需要到CA申请证书,HTTP不需要
>HTTPS密文传输,HTTP明文传输
> HTTPS=HTTP+加密+认证+完整性保护,较HTTP安全
>连接方式不同,HTTPS默认使用443端口,HTTP使用80端口
有没有使用过云主机(云服务)?
答:云服务器运行商提供的远程服务
有没有做过数据库优化?
1、查找定位慢查询:explain
2、建立索引:创建合适的索引,加速查询
3、分表: 当一张表的数据比较多或者某些字段的值特别占空间,采用水平拆分或者垂直拆分
4、读写分离:服务器性能不能满足时,采用读写分离方式进行集群
5、使用缓存:redis
查找定位慢查询:
在项目自验项目转测试之前,在启动MySQL数据库是开启慢查询,并且把执行慢的语句写到日志中,在运行一定时间后,通过查看日志找到慢查询语句。
使用explain +sql
慢查询语句,来详细分析语句的问题。
优化技巧:
允许冗余字段、选择合适的存储引擎、索引(占用磁盘、dml操作影响性能、不做查询没意义,字段
内容变化不频繁)组合索引(最左匹配,如果不以前面的字段、必须包含第一个字段为查询条件,索引失效)
对于like索引字段,如果是aaa%,索引有效,否则无效
如果条件中有or,每个字段都必须有索引,否则索引无效
如果列类型是字符串,在条件中必须用单引号引用起来,否则索引失效
如果mysql估计使用全部扫描比使用索引快,则不适用索引
sql查询优化器认为全表扫描效率比索引扫描高,就会使用全表扫描。
那么sql优化器是如何计算扫描效率的呢?
分表:水平分表(按行)和垂直分表(按列)
因为单个物理数据库的资源跟连接数是有限制的,所以在数据量或者并发量较大的情况下,需要将一个数据库拆分成多个数据库。 mysql数据库纪录达到百万级时,查询性能会变慢,容易造成表锁,甚至堆积很多链接,直接挂掉,水平分表会很大程度减少这些压力。<—— 水平分表(按行)
如果一张表中某个字段的值非常多(长文本、二进制等),而且只有很少的情况下会查询,这时候应该将其单独存储,用外键关联起来!<—— 垂直分表(按列)
考试详情:一般只关注分数,不关注详情
分库分表会带来什么问题?
分布式事务、跨库join、count、全局排序 (需要将多库、表的数据提取进行聚合处理)
水平分表策略:
1、按时间分(也是一种范围分)
有一定的局限性,当数据有较强的时效性,很少有用户会查询几个月前的数据,可按月分表
2、按区间范围分
一般在有严格自增id需求上,如按用户ID水平分表
table1:user_id 从1 - 100w
table2 : user_id 从101 - 200w
3、hash分表(用的最多)
通过一个原始目标的ID或者名称按一定的hash算法计算出数据存储的表名,然后访问相应的表。
分库分表的坑
1.分库分表的坑之扩容
分库、分表、垂直拆分和水平拆分
-
分库: 因一个数据库支持的最高并发访问数是有限的,可以将一个数据库的数据拆分到多个库中,来增加最高并发访问数。
-
分表: 因一张表的数据量太大,用索引来查询数据都搞不定了,所以可以将一张表的数据拆分到多张表,查询时,只用查拆分后的某一张表,SQL 语句的查询性能得到提升。
-
分库分表优势:分库分表后,承受的并发增加了多倍;磁盘使用率大大降低;单表数据量减少,SQL 执行效率明显提升。
-
水平拆分: 把一个表的数据拆分到多个数据库,每个数据库中的表结构不变。用多个库抗更高的并发。比如订单表每个月有500万条数据累计,每个月都可以进行水平拆分,将上个月的数据放到另外一个数据库。
-
垂直拆分: 把一个有很多字段的表,拆分成多张表到同一个库或多个库上面。高频访问字段放到一张表,低频访问的字段放到另外一张表。利用数据库缓存来缓存高频访问的行数据。比如将一张很多字段的订单表拆分成几张表分别存不同的字段(可以有冗余字段)。
-
分库、分表的方式:
-
根据租户来分库、分表。
-
利用时间范围来分库、分表。
-
利用 ID 取模来分库、分表。
-
坑:
分库分表是一个运维层面需要做的事情,有时会采取凌晨宕机开始升级。可能熬夜到天亮,结果升级失败,则需要回滚,其实对技术团队都是一种煎熬。
怎么做成自动的来节省分库分表的时间?
-
双写迁移方案:迁移时,新数据的增删改操作在新库和老库都做一遍。
-
使用分库分表工具 Sharding-jdbc 来完成分库分表的累活。
-
使用程序来对比两个库的数据是否一致,直到数据一致。
坑:
分库分表看似光鲜亮丽,但分库分表会引入什么新的问题呢?
垂直拆分带来的问题
-
依然存在单表数据量过大的问题。
-
部分表无法关联查询,只能通过接口聚合方式解决,提升了开发的复杂度。
-
分布式事处理复杂。
水平拆分带来的问题
-
跨库的关联查询性能差。
-
数据多次扩容和维护量大。
-
跨分片的事务一致性难以保证。
分布式事务的坑
怎么理解事务?
-
事务可以简单理解为要么这件事情全部做完,要么这件事情一点都没做,跟没发生一样。
-
在分布式的世界中,存在着各个服务之间相互调用,链路可能很长,如果有任何一方执行出错,则需要回滚涉及到的其他服务的相关操作。比如订单服务下单成功,然后调用营销中心发券接口发了一张代金券,但是微信支付扣款失败,则需要退回发的那张券,且需要将订单状态改为异常订单。
保证分布式中的事务正确执行
分布式事务的几种主要方式
-
XA 方案(两阶段提交方案)
-
TCC 方案(try、confirm、cancel)
-
SAGA 方案
-
可靠消息最终一致性方案
-
最大努力通知方案
XA 方案原理
XA 方案
-
事务管理器负责协调多个数据库的事务,先问问各个数据库准备好了吗?如果准备好了,则在数据库执行操作,如果任一数据库没有准备,则回滚事务。
-
适合单体应用,不适合微服务架构。因为每个服务只能访问自己的数据库,不允许交叉访问其他微服务的数据库。
TCC 方案
-
Try 阶段:对各个服务的资源做检测以及对资源进行锁定或者预留。
-
Confirm 阶段:各个服务中执行实际的操作。
-
Cancel 阶段:如果任何一个服务的业务方法执行出错,需要将之前操作成功的步骤进行回滚。
应用场景:
-
跟支付、交易打交道,必须保证资金正确的场景。
-
对于一致性要求高。
缺点:
-
但因为要写很多补偿逻辑的代码,且不易维护,所以其他场景建议不要这么做。
Sega 方案
基本原理:
-
业务流程中的每个步骤若有一个失败了,则补偿前面操作成功的步骤。
适用场景:
-
业务流程长、业务流程多。
-
参与者包含其他公司或遗留系统服务。
优势:
-
第一个阶段提交本地事务、无锁、高性能。
-
参与者可异步执行、高吞吐。
-
补偿服务易于实现。
缺点:
-
不保证事务的隔离性。
可靠消息一致性方案
可靠消息一致性方案
基本原理:
-
利用消息中间件
RocketMQ
来实现消息事务。 -
第一步:A 系统发送一个消息到 MQ,MQ将消息状态标记为
prepared
(预备状态,半消息),该消息无法被订阅。 -
第二步:MQ 响应 A 系统,告诉 A 系统已经接收到消息了。
-
第三步:A 系统执行本地事务。
-
第四步:若 A 系统执行本地事务成功,将
prepared
消息改为commit
(提交事务消息),B 系统就可以订阅到消息了。 -
第五步:MQ 也会定时轮询所有
prepared
的消息,回调 A 系统,让 A 系统告诉 MQ 本地事务处理得怎么样了,是继续等待还是回滚。 -
第六步:A 系统检查本地事务的执行结果。
-
第七步:若 A 系统执行本地事务失败,则 MQ 收到
Rollback
信号,丢弃消息。若执行本地事务成功,则 MQ 收到Commit
信号。 -
B 系统收到消息后,开始执行本地事务,如果执行失败,则自动不断重试直到成功。或 B 系统采取回滚的方式,同时要通过其他方式通知 A 系统也进行回滚。
-
B 系统需要保证幂等性。
最大努力通知方案
基本原理:
-
系统 A 本地事务执行完之后,发送消息到 MQ。
-
MQ 将消息持久化。
-
系统 B 如果执行本地事务失败,则
最大努力服务
会定时尝试重新调用系统 B,尽自己最大的努力让系统 B 重试,重试多次后,还是不行就只能放弃了。转到开发人员去排查以及后续人工补偿。
几种方案如何选择
-
跟支付、交易打交道,优先 TCC。
-
大型系统,但要求不那么严格,考虑 消息事务或 SAGA 方案。
-
单体应用,建议 XA 两阶段提交就可以了。
-
最大努力通知方案建议都加上,毕竟不可能一出问题就交给开发排查,先重试几次看能不能成功。
分布式ID生成策略
redis自增;
雪花算法;
MySQL自增主键;
uuid;
读写分离
当一台数据库访问达到瓶颈(一台数据库最大支持数有限),用户并发访问过多,一台服务器无法支撑,这时候可以集群处理,
最常用的是读写分离。
主从同步:
数据库最终会将数据持久化到磁盘上,集群中的数据库数据是一致的。主库用来写,其他数据库从主上同步
读写分离:
使用负载均衡来实现(主库用来写,从库支持读)
数据库优化之缓存:
在持久层和数据库之间添加缓存层 用户的数据已经缓存,用户将直接从缓存中读取,不操作数据库,缓存是操作内存
级的,访问速度快。
作用:减少数据库服务器压力,提升访问速度
hibernate的二级缓存无法支持分布式
redis作为中央缓存,集中管理
语句优化技巧:
DDL优化:
1、禁用索引:提升导入数据性能 导入前去索引 导入数据 加回索引
DML优化:
变多次提交为一次
JDBC 如何高效插入几百万条数据?
1、变多次提交为一次
2、使用批量操作
redis:中央缓存
web集群时作为session
缓存队列等
保存对象方式:JSON字符串、字节
数据淘汰机制:从已设置过期时间的数据里挑选最近最少使用的数据。
产品:充分考虑扩展性
zookeeper集群原理
zookeeper是一个分布式协调框架 文件系统+监听通知机制
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper
会通知客户端。
四种类型节点(持久节点、临时节点、持久顺序节点、临时顺序节点)
持久节点: 存储到磁盘
临时节点: 声明绑定周期、连接断开,节点信息直接删除
三大角色:领导者 跟随者 观察者
watcher 事件通知(节点变化、新增、修改、删除)
主节点写 如果请求落到从,从节点会将请求转发给主,然后再同步到从节点
主节点会将写请求以严格的zxid,全局唯一且顺序
如何初始化时加载数据到redis中?
在controller层的对象implements InitializingBean
回调afterPropertiesSet
Cookie和Session的区别
总结一下Object这个基类
重写
equals()
方法,就必须重写hashCode()
的方法
equals()
方法默认是比较对象的地址,使用的是==
等值运算符
hashCode()
方法对底层是散列表的对象有提升性能的功能同一个对象(如果该对象没有被修改):那么重复调用
hashCode()
那么返回的int是相同的!
hashCode()
方法默认是由对象的地址转换而来的
equals()
方法还有5个默认的原则:
自反性--->调用
equals()
返回的是true,无论这两个对象谁调用equals()
都好,返回的都是true一致性--->只要对象没有被修改,那么多次调用还是返回对应的结果!
传递性--->
x.equals(y)
和y.equals(z)
都返回true,那么可以得出:x.equals(z)
返回true对称性--->
x.equals(y)
和y.equals(x)
结果应该是相等的。传入的参数为null,返回的是false