1、nginx相关
1.1、什么是正向代理
正向代理是一种网络代理服务器的运作模式,它充当客户端与外部服务器之间的中间人,代理客户端发起的请求,并将这些请求转发给外部服务器。在正向代理的架构中,客户端无法直接访问目标服务器,而是通过正向代理服务器来代为发起连接。以下是正向代理的基本工作原理:
- 客户端发送请求:客户端向正向代理服务器发起请求,请求中包含了要访问的目标服务器的信息。
- 代理服务器转发请求:正向代理服务器接收到客户端的请求后,会代表客户端向目标服务器发起实际的连接请求。
- 目标服务器响应:目标服务器接收到代理服务器发起的连接请求后,会向代理服务器返回响应数据。
- 代理服务器响应客户端:代理服务器再将目标服务器的响应数据返回给客户端,客户端则认为这些数据是直接从代理服务器获取的。
常见使用场景:访问受限资源、保护客户端隐私、访问跨境内容
总的来说,正向代理充当客户端的代理,代替客户端发起连接和获取数据,为客户端提供了更多的灵活性和隐私保护。
1.2、什么是反向代理
反向代理(Reverse Proxy)是一种代理服务器的部署方式,它代表服务器接收客户端的请求,并将这些请求转发给内部的服务器。与正向代理不同,反向代理是对外隐藏了真实的服务器,并充当了客户端与内部服务器之间的中间人。客户端认为它们直接与反向代理通信,而不知道实际处理请求的是内部的服务器。
反向代理的工作流程如下:
- 客户端发送请求:客户端向反向代理服务器发送请求,通常是访问某个网站或服务。
- 反向代理处理请求:反向代理服务器接收到客户端的请求后,根据配置的规则和负载均衡策略,将请求转发给内部的一个或多个服务器。
- 内部服务器响应:内部服务器接收到来自反向代理的请求后,处理请求并生成响应数据。
- 反向代理返回响应:反向代理服务器将内部服务器的响应数据返回给客户端,客户端认为这些数据是直接从反向代理获取的。
反向代理的主要作用包括负载均衡、安全防护、缓存加速等。通过反向代理,可以提高服务器的性能、可靠性和安全性,同时隐藏了内部服务器的实际地址,增强了系统的安全性。
总的来说,反向代理充当服务器的代理,代替服务器处理客户端的请求和响应,为服务器提供了更好的性能和安全保护。
1.3、什么是CDN服务
CDN(内容分发网络)是指一组分布在全球各地的服务器网络,用于加速互联网上静态和动态内容的传输。CDN 服务通过将内容缓存到离用户更近的服务器上,以提高用户访问这些内容的速度和性能。CDN 的基本原理是利用就近性原则,让用户能够从距离更近、网络质量更好的服务器获取所需的内容,而不必直接访问原始服务器。
CDN 服务的主要特点包括:
- 加速访问速度:通过在全球各地部署服务器,CDN 可以使用户能够从距离更近的服务器获取内容,减少网络延迟,提高访问速度。
- 负载均衡:CDN 可以根据用户的位置和网络状况,自动将请求分发到最优的服务器,从而实现负载均衡,提高服务的稳定性和可靠性。
- 减轻源服务器压力:CDN 可以缓存大量的静态资源,并在用户请求时直接返回,减轻了源服务器的负担,提高了源服务器的处理能力。
- 安全防护:CDN 可以提供一定程度的安全防护,例如防御 DDoS 攻击、恶意请求等,保护源服务器免受攻击。
CDN 服务通常用于加速网站的访问速度,提高用户体验,同时也可以用于视频直播、软件分发等领域。许多大型的互联网公司和网站都会使用 CDN 服务来优化其内容的传输和分发。
总的来说,CDN 服务通过在全球范围内部署服务器,提高了内容的传输速度、稳定性和安全性,为用户和网站提供了更好的体验和保护。
1.4、Nginx的负载均衡
Nginx 是一个常用的高性能的 Web 服务器和反向代理服务器,它也可以用作负载均衡器。通过 Nginx 的负载均衡功能,可以将客户端的请求分发到多台后端服务器上,从而提高系统的性能、可靠性和可扩展性。
Nginx 实现负载均衡的方式通常有两种:基于轮询的负载均衡和基于权重的负载均衡。
- 基于轮询的负载均衡:Nginx 默认的负载均衡方式是基于轮询的。当有新的请求到达时,Nginx 会按照事先配置好的后端服务器列表顺序,依次将请求转发给这些服务器。这样可以实现比较简单的负载均衡,但无法根据后端服务器的负载情况进行动态调整。
- 基于权重的负载均衡:除了默认的轮询方式外,Nginx 还支持基于权重的负载均衡。通过设置不同后端服务器的权重,可以让 Nginx 按照这些权重比例来分配请求,从而实现更灵活的负载均衡策略。
另外,Nginx 也支持其他负载均衡算法,如 IP 哈希、最小连接数等。这些算法可以根据具体的业务需求和场景选择合适的负载均衡策略。
1.5、Nginx限流怎么做
在 Nginx 中实现限流可以通过使用 limit_req 模块来实现。limit_req 模块可以根据客户端的请求数或请求频率来对请求进行限制,以保护后端服务器免受过多的请求压力。
以下是一种使用 limit_req 模块进行限流的配置示例:
http { limit_req_zone $binary_remote_addr zone=limit:10m rate=10r/s; server { location / { limit_req zone=limit burst=20 nodelay; # 其他配置项 } } }
上述配置中,我们首先使用 limit_req_zone 指令定义了一个名为 limit 的限流区域,该区域将存储客户端的限流状态信息。$binary_remote_addr 是用于区分不同客户端的关键字,它使用客户端的 IP 地址进行标识。10m 表示限流区域的内存大小,可以根据需要进行调整。rate=10r/s 表示每秒钟允许的平均请求数为 10。
接下来,在 location 配置块中,我们使用 limit_req 指令来应用限流策略。zone=limit 将限制区域设置为之前定义的 limit,burst=20 表示在达到限流阈值之后,允许的最大突发请求数为 20。nodelay 选项表示不延迟请求,即超过限流阈值的请求将被立即返回 503 错误。
通过以上配置,Nginx 将会对每个客户端 IP 地址在指定的时间窗口内进行请求计数,并根据设置的限流速率进行限制。如果某个客户端的请求数超过了限制,后续的请求将被暂时拒绝或延迟返回,直到请求速率降低到限定的阈值以下。
2、分布式事务
2.1、CAP定理
分布式系统有三个指标:
- Consistency(一致性)
- Availability(可用性)
- Partition tolerance (分区容错性)
它们的第一个字母分别是 C、A、P。Eric Brewer认为任何分布式系统架构方案都不可能同时满足这3个目标,这个结论就叫做 CAP 定理。
2.2、BASE理论
既然分布式系统要遵循CAP定理,那么问题来了,我到底是该牺牲一致性还是可用性呢?如果牺牲了一致性,出现数据不一致该怎么处理?
人们在总结系统设计经验时,最终得到了一些心得:
- Basically Available (基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
- Soft State(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态。
- Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。
以上就是BASE理论。
2.3、二阶段提交
在分布式系统中,二阶段提交(Two-Phase Commit,简称 2PC)是一种经典的协议,用于保证多个参与方在分布式事务中的一致性。
2PC 协议由两个阶段组成:
- 准备阶段(Prepare Phase):
- 协调者(通常是事务管理器)向所有参与方发送准备请求,并等待它们的响应。参与方执行本地事务,并将事务的执行结果和准备状态返回给协调者。
- 提交阶段(Commit Phase):
- 如果所有参与方的准备请求都成功,并且没有发生错误,协调者则发送提交请求给所有参与方。参与方接收到提交请求后,将正式提交事务,并释放相关资源。
如果在任何一个参与方的准备阶段出现错误、超时或者拒绝提交的情况,协调者将发送回滚请求给所有参与方,要求它们撤销之前的操作并回滚事务。
2.4、SEATA模式
Seata 是一个开源的分布式事务解决方案,它提供了多种模式来支持不同场景下的分布式事务处理。主要的 Seata 分布式事务模式包括 AT 模式(TCC 模式)、TCC 模式、SAGA 模式和XA 模式。
- AT 模式(TCC 模式):
- AT 模式是 Seata 最基础的分布式事务模式,也称为 TCC(Try-Confirm-Cancel)模式。在 AT 模式中,事务分为三个阶段:尝试(Try)、确认(Confirm)和取消(Cancel)。应用程序需要实现这三个阶段的方法来保证事务的一致性。
- TCC 模式:
- TCC 模式和 AT 模式类似,也是基于 Try-Confirm-Cancel 的思想,但相比于 AT 模式更加灵活,允许业务逻辑更细粒度地控制事务的各个阶段。
- SAGA 模式:
- SAGA 模式是一种基于状态的分布式事务模式,在每个微服务内部处理自身的事务,并通过事件机制跨服务通信,从而实现全局事务的一致性。
- XA 模式:
- XA 模式是传统的两阶段提交协议,通过 XA 接口来协调多个数据库事务。Seata 通过支持 XA 模式来实现分布式事务的一致性。
2.5、Seata是强一致性事务吗
一般使用的是SEATA的AT模式;而AT模式是每个分支事务独立提交事务;所以是非强一致性事务。
2.6、柔性事务与刚性事务的区别
柔性事务满足BASE理论(基本可用,最终一致)
Basically Available基本可用
Soft-state 软状态/柔性事务
Eventual Consistency 最终一致性
刚性事务满足ACID理论
Atomic(原子性):要么都成功,要么都失败
Consistent(一致性):数据应该不被破坏
Isolate(隔离性):用户间操作不相混淆
Durable(持久性):永久保存
3、分布式锁
3.1、什么场景下要使用分布式锁
分布式锁在以下场景中非常有用:
- 共享资源的互斥访问:
- 当多个分布式节点需要同时访问某个共享资源(例如数据库、文件系统)时,为了保证数据的一致性和避免冲突,可以使用分布式锁来确保同一时间只有一个节点能够访问该资源。
- 避免重复操作:
- 在某些情况下,需要防止重复操作,即同一个任务在分布式环境中只能被执行一次。使用分布式锁可以确保只有一个节点能够成功获取锁并执行任务,其他节点则被阻塞或放弃执行。
- 控制并发流量:
- 在高并发环境下,为了避免系统资源耗尽,可以使用分布式锁来控制并发流量。只有获取到锁的节点才能执行某个操作,其他节点需要等待锁释放后才能继续执行。
- 避免竞态条件:
- 当多个节点同时进行某个操作时,可能会产生竞态条件(Race Condition),导致数据不一致或者错误的结果。通过使用分布式锁,可以在关键的操作中保持原子性,避免竞态条件的发生。
- 任务调度与协调:
- 在分布式任务调度中,可以使用分布式锁来协调任务的执行顺序和避免重复执行。只有获取到锁的节点才能执行任务,其他节点需要等待或者跳过。
更常见的场景是:防止超卖 问题
3.2、分布式锁的实现方案有哪些
- 基于数据库的分布式锁:
- 可以利用数据库的唯一性约束或者悲观锁来实现分布式锁。通过在数据库中创建一个表或者记录,利用事务的特性来确保锁的唯一性。
- 基于 Redis 的分布式锁:
- 使用 Redis 的 SETNX(SET if Not eXists)指令来实现简单的分布式锁。通过在 Redis 中设置一个键值对表示锁,利用原子操作来确保锁的互斥性。或者直接采用 redisson 客户端;
- 基于 ZooKeeper 的分布式锁:
- 利用 ZooKeeper 的临时顺序节点和 Watch 机制来实现分布式锁。通过创建临时顺序节点来竞争锁,同时利用 Watch 机制监听节点变化来实现分布式锁的释放和获取。
3.3、如何选择分布式锁方案
1、redisson:可以使用在并发高,性能要求高的场景;
2、zookeeper:采用cp模式保证高可靠性,对于更高要求绝对可靠的场景;
3.4、redisson分布式锁如何应用
在 Redisson 中使用分布式锁通常包括以下步骤:
- 创建 Redisson 客户端连接到 Redis 服务器。
- 通过 Redisson API 获取分布式锁对象。
- 在关键代码段中使用分布式锁的加锁和解锁方法来控制对共享资源的访问。
例如,在 Redisson 中获取分布式锁的代码示例可能如下所示:
Config config = new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redisson = Redisson.create(config); RLock lock = redisson.getLock("myLock"); try { // 尝试加锁,最多等待100秒,并且锁的自动过期时间为30秒 boolean isLocked = lock.tryLock(100, 30, TimeUnit.SECONDS); if (isLocked) { // 成功获取到锁,执行关键代码段 // ... } else { // 获取锁失败,做相应处理 // ... } } finally { // 释放锁 lock.unlock(); }
3.5、如何实现分布式锁的可重入
可重入锁意思:是对于同一线程可以多次获取锁;那不同线程之间同一把锁不能重复获取怎么保证线程可重入获取锁呢?
解决:我们可以通过维护当前持有锁的计数来实现可重入功能。
- 加锁的时候,因为保存了锁的线程标识,后续再次获取锁,先看是否是同一个线程,如果是的话只对锁计数进行递增
- 解锁时,对锁计数进行递减,同时刷新锁的过期时间。如果计数为 0,最终才释放锁
3.6、如何提升分布式锁性能
1、锁定的代码块尽量的少,和尽早的释放锁;
2、redis集群有助于redis的处理效率;
3、库存数据不一定使用分布式锁,而是可将库存放入redis中,然后递减方式来实现扣减;
4、复杂一点的实现也可以采用:分段分布式锁,将库存分成好几个数据,然后锁这几个数据,也能提高性能
4、redis相关
4.1、Redis挂了数据如何处理
1、redis有集群,不会轻易不可用;若某个主节点挂了则通过sentinel哨兵自动用从节点替换为主节点;
2、若redis真不可使用;可以支持查询数据库,业务还是一样可执行;然后再修复redis;
3、如果要完整的思考在redis挂掉的情况下,微服务需要高效稳定运行,那么可以在每台微服务中都设置本地缓存(hashMap、memcache、caffeineCache都可以)
4.2、redis常见数据类型
Redis 是一种基于内存的键值存储数据库,支持多种数据类型,每种数据类型都有其特定的用途和适用场景。以下是 Redis 中常见的数据类型:
- 字符串(String):
- 最简单的数据类型,可以存储字符串、整数或者浮点数。常用命令包括 SET、GET、INCR 等。
- 哈希表(Hash):
- 键值对集合,其中每个键都包含一个字段和值的映射表。适合存储对象的属性集。常用命令包括 HSET、HGET、HDEL 等。
- 列表(List):
- 一个有序的字符串元素集合,可在头部或尾部插入元素。适合实现队列、栈等数据结构。常用命令包括 LPUSH、RPUSH、LPOP、RPOP 等。
- 集合(Set):
- 无序且唯一的字符串集合,支持交集、并集、差集等操作。适合存储不重复的元素。常用命令包括 SADD、SREM、SMEMBERS 等。
- 有序集合(Sorted Set):
- 类似集合,但每个元素都关联一个分数(score),可以按照分数排序。适合实现排行榜、范围查找等功能。常用命令包括 ZADD、ZRANGE、ZREVRANK 等。
4.3、项目中缓存的数据类型
缓存在redis中的数据类型有:
- 字符类型的常规缓存内容(验证码)
- 列表类型的有首页广告列表
- 集合类型的热门商品
4.4、redis主从集群与分片集群的区别
- 主从集群(Master-Slave Replication):
- 主从集群是通过主节点(Master)和若干个从节点(Slave)组成的集群。主节点负责处理写操作和广播读操作给所有从节点,从节点负责处理读操作并复制主节点的数据。
- 主从集群的优点是简单易用,从节点可以提高读取性能和数据冗余,同时也能在主节点故障时提供故障转移。提高redis的可用性
- 分片集群(Sharded Cluster):
- 分片集群将数据分片存储在多个节点上,每个节点负责存储部分数据。客户端根据一定的规则将数据请求路由到相应的节点上。
- 分片集群的优点是能够横向扩展,提高了整体的读写性能和存储容量;同时也能提高系统的可用性和容错能力。
总的来说,主从集群适合简单场景下的读写分离和故障恢复,而分片集群适合需要大规模扩展和高性能的场景。