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):
- 分片集群将数据分片存储在多个节点上,每个节点负责存储部分数据。客户端根据一定的规则将数据请求路由到相应的节点上。
- 分片集群的优点是能够横向扩展,提高了整体的读写性能和存储容量;同时也能提高系统的可用性和容错能力。
总的来说,主从集群适合简单场景下的读写分离和故障恢复,而分片集群适合需要大规模扩展和高性能的场景。
4.5、redis持久化策略
Redis 中常用的两种持久化策略:
- RDB(Redis DataBase):
- RDB 是将 Redis 在内存中的数据定期保存到磁盘上的一种持久化方式。通过快照的方式,将数据保存为一个压缩的二进制文件(.rdb 文件)。
- RDB 的优点是备份数据快速,适合用于数据恢复和全量备份;同时由于是紧凑的二进制文件,可以减少磁盘空间的占用。
- RDB 的缺点是可能会出现数据丢失,因为数据是定期保存的;另外,在数据量较大时,生成快照可能会影响 Redis 的性能。
- AOF(Append Only File):
- AOF 是通过将 Redis 所有写操作追加到文件末尾的方式来记录数据变动的一种持久化方式。当 Redis 重启时,可以通过重新执行 AOF 文件中的写操作来还原数据。
- AOF 的优点是数据更加安全,可以保证每次写操作都被记录下来;同时,AOF 文件可以提供更好的数据持久性保证。
- AOF 的缺点是相对于 RDB,AOF 文件通常会比较大,可能会增加磁盘的占用;另外,AOF 文件的恢复速度可能会比 RDB 恢复慢一些。
除了单独使用 RDB 或 AOF 外,Redis 还支持同时使用 RDB 和 AOF 两种持久化方式,以提供更好的数据持久性和灾难恢复能力。此外,Redis 也支持实时数据同步(Replication)来提高数据的可用性和容错能力。
4.6、redis内存淘汰策略
Redis支持8种不同的内存淘汰策略:
- noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略。
- volatile-ttl: 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰
- allkeys-random:对全体key ,随机进行淘汰。也就是直接从db->dict中随机挑选
- volatile-random:对设置了TTL的key ,随机进行淘汰。也就是从db->expires中随机挑选。
- allkeys-lru: 对全体key,基于LRU算法进行淘汰
- volatile-lru: 对设置了TTL的key,基于LRU算法进行淘汰
- allkeys-lfu: 对全体key,基于LFU算法进行淘汰
- volatile-lfu: 对设置了TTL的key,基于LFI算法进行淘汰
比较容易混淆的有两个算法:
- LRU(LeastRecentlyUsed),最近最久未使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
- LFU(LeastFrequentlyUsed),最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高。
4.7、redis数据删除
Redis的过期KEY删除策略有两种:
- 惰性删除
- 周期删除
惰性删除,顾明思议就是过期后不会立刻删除。Redis会在每次访问KEY的时候判断当前KEY有没有设置过期时间,如果有,过期时间是否已经到期。
周期删除:顾明思议是通过一个定时任务,周期性的抽样部分过期的key,然后执行删除。
4.8、redis是单线程吗
Redis 4.0 以前是完全单线程;
Redis从4.0开始,也有后台线程在工作,处理一些较为缓慢的操作,例如无用连接的释放、大 key 的删除等;
Redis 6.0引入多线程IO,只是用来处理网络数据的读写和协议的解析,而执行命令依旧是单线程,所以不需要去考虑set/get、事务、lua等的并发问题
4.9、为什么单线程快
- 纯内存操作,避免大量访问数据库,减少直接读取磁盘数据,redis将数据储存在内存里面,读写数据的时候都不会受到硬盘 I/O 速度的限制,所以速度快.
- 单线程操作,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗.
- 采用了非阻塞I/O 多路复用机制.
4.10、redis红锁
问题:
在redis集群中;如果请求一个分布式锁成功;但slave还没有复制同步这个锁,master宕机了;再次去加锁的时候会从继任了master的原slave上申请加锁,也会成功。导致同一个锁被获取了不止一次。
解决:
对集群的每个节点进行加锁,如果大多数(N/2+1)加锁成功了,则认为获取锁成功。
Redisson实现了红锁;但是它对每个加锁的实现,不能保证每个锁落在不同的master上。不建议使用
直接使用Redisson的普通锁即可。
5、mq相关
5.1、为什么要使用MQ
1、分布式系统下可以实现异步处理业务,削峰填谷的功能;
2、实现消费者和生产者之间的解耦;——系统解耦
5.2、MQ应用场景
应用场景1:当后台系统对数据进行添加、删除、修改后,将会发送一个消息,接收到此消息的微服务可执行对应业务。如:更新ElasticSearch的数据,更新动态,支付状态检查
应用场景2:用户登录、注册时,向用户发送短信验证码。
5.3、MQ如何保障发送消息可靠
简易快速容易实现的做法:
1、开启生产者重试机制;
2、启用生产者发送消息后确认机制(ConfirmCallback)
理论上更可靠方案(一般不那么搞):
- 把消息数据写入数据库,用状态码来控制消息发送状态。
- 开启定时任务,间隔3秒,查询未发送的消息。
- 调用消息生产者,发送消息到MQ中间件。
- 消息生产者,设置confirmCallback确认回调对象,判断ack
-- true: 消息发送成功,修改消息发送状态为: 已发送。
-- false: 消息发送失败。定时任务重发
5.4、MQ如何保障消费消息可靠
比较现实和常见的做法:
1、消费者确认机制
2、设置失败重试机制
3、重试失败后投递到其它交换机再处理
4、主动查询业务(兜底方案)
理论上方案:
- 接收到消息后,直接存入数据库(消息幂等的处理)。
- 定时任务定时扫描数据库未处理消息。
5.5、MQ死信队列(延迟队列)
当一个队列中的消息满足下列情况之一时,可以成为死信(dead letter):
- 消费者使用basic.reject或 basic.nack声明消费失败,并且消息的requeue参数设置为false
- 消息是一个过期消息,超时无人消费
- 要投递的队列消息满了,无法投递
如果一个队列中的消息已经成为死信,并且这个队列通过dead-letter-exchange属性指定了一个交换机,那么队列中的死信就会投递到这个交换机中,而这个交换机就称为死信交换机(Dead Letter Exchange)。而此时加入有队列与死信交换机绑定,则最终死信就会被投递到这个队列中;这个队列称为 死信队列。
一般情况;都是对一个消息设置过期时间,然后再到时间之后接收消息,达到延迟处理的效果;这样的死信队列也被称为延迟队列。
5.6、如何防止消息重复消费
利用去重表来解决,每次接收到消息之后,先从去重表查询该消息是否已经消费,如果已经消费就不处理本来的业务,否则处理本来的业务并且往去重表添加一行消息去重记录。
5.7、如何解决消息解压问题
- 消息过多,消费者消费速度太慢。
- 多个消费者并发消费
- 多线程并发消费
- 设置消息存活时间(TTL) Time To Live
- 设置队列中存储消息的界限(Lim) limit
- 消费者消费失败,消息还在业务队列中。
- 再重试一次,如果还不行,扔到死信队列,避免队列阻塞。
5.8、RabbitMQ的消息模式
模式有常见的五种:
- 简单队列模式:一个生产者,一个消费者,一个消息被一个消费者接收;
- 工作队列模式:一个生产者,生产一个消息到一个队列中,多个消费者同时监听这个队列;消息被竞争消费。(默认平均,可配置为 能者多得)
- 交换机模式
- Fanout 广播模式:每个绑定到该类交换机的队列都能接收到消息,实现广播的效果
- Direct 定向模式:每个绑定到交换机的队列,还有一个路由key;发送的key与绑定同类key的队列才能接收到消息
- Topic 主题模式:每个绑定到交换机的队列,还有一个路由key;发送的key与绑定同类key的队列才能接收到消息;这个key可以使用通配符;*表示一个字符,#表示多个
6、elasticsearch相关
6.1、正向索引
正向索引:以文档的ID为关键字,表中记录文档中每个字的位置信息,查找时扫描表中每个文档中字的信息直到找出所有包含查询关键字的文档
正向索引是最传统的,根据id索引的方式。但根据词条查询时,必须先逐条获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程。
6.2、倒排索引
创建倒排索引是对正向索引的一种特殊处理和应用,流程如下:
- 将每一个文档的数据利用分词算法根据语义拆分,得到一个个词条
- 创建表,每行数据包括词条、词条所在文档id、位置、出现次数等信息
- 因为词条唯一性,可以给词条创建正向索引
倒排索引,是先找到用户要搜索的词条,根据词条得到保护词条的文档的id,然后根据id获取文档。是根据词条找文档的过程。
6.3、es索引文档过程
Elasticsearch 中索引文档的一般过程:
- 创建索引(Index):在 Elasticsearch 中,首先需要为文档指定一个索引,索引是文档的逻辑容器,类似于关系型数据库中的数据库。可以通过 REST API 或者编程客户端创建索引。
- 定义映射(Mapping):在创建索引时,可以定义文档的映射,即每个字段的数据类型和属性。映射定义了文档的结构,包括字段名、数据类型、分词器等信息。
- 索引文档(Indexing):一旦索引和映射准备就绪,就可以开始索引文档了。文档是 Elasticsearch 存储、索引和搜索的基本单位,通常以 JSON 格式表示。将文档发送到 Elasticsearch 的特定索引中,Elasticsearch 将文档解析、索引并存储。
- 文档存储:Elasticsearch 将文档存储在倒排索引中,以便快速地进行全文搜索。文档被分割成多个字段,并根据字段类型进行索引化处理。如果是要索引且需要分词的,则先利用分词器进行分词,过滤,然后再形成倒排索引。
6.4、es搜索步骤
- 创建搜索请求对象,指定索引库名
- 设置搜索请求对象参数;搜索类型(范围、词条、搜索关键字分词搜索等)、分页、排序、高亮、聚合等;
- 执行请求;
- 解析响应结果
6.5、es相对mysql的特点是什么
MySQL更擅长的是事务类型的操作,存储结构化数据;
ES更擅长的是海量数据的搜索,分析和计算,不支持事务;存储非结构化数据;
6.6、es集群情况
ES集群架构6个节点,索引:3分片;ES调优:在设计映射阶段针对数据搜索情况合理设置数据类型,尽可能多的设置keyword类型域;根据需要设置不同域的索引、查询分词器;查询时尽可能少使用模糊和相似查询。
如果数据量增长迅速,数据过大如何解决?可以重新创建索引(指定更多的集群节点和分片),然后将原数据导入再次导入。(注意:es在创建索引后不能直接扩容)
6.7、es采用什么数据结构
由索引、类型、文档、字段构成。
- index索引
数据属于哪个索引?不同的数据用不同的索引来区分。
比如 当前有两个索引:
Account : 这个索引是用来存放账户数据的
Book:这个索引是用来存放书本数据的。
- type类型
指明数据的类型,一个索引里可以有多个类型
比如Account类型有:访客、普通用户、管理员
比如Book类型有:小说、写真、教材
- document文档
描述的是具体的一条数据记录,一个类型里可以有多个文档。
- field字段
描述具体记录中的某个字段,一条文档记录中可以有多个字段。
7、docker相关
7.1、docker与虚拟机的区别
- 虚拟机(Virtual Machine):虚拟机是利用虚拟化技术在物理硬件上创建一个或多个完整的虚拟计算机。每个虚拟机都包含自己的操作系统、应用程序和资源,运行在宿主机的虚拟化软件(如 VMware、VirtualBox 等)上。
- Docker:Docker 是一种容器化平台,通过使用容器技术将应用程序及其依赖项打包在一个称为容器的单元中。Docker 容器与宿主机共享操作系统内核,但相互隔离,可以在同一宿主机上运行多个容器。
7.2、常用命令
- docker run:运行一个新的容器。
- 例如:docker run -it --name mycontainer ubuntu:latest /bin/bash,这将在名为 "mycontainer" 的容器中运行最新版本的 Ubuntu 镜像,并启动一个交互式的 bash shell。
- docker ps:列出当前正在运行的容器。
- 例如:docker ps,这将列出当前正在运行的所有容器,包括容器 ID、名称、镜像、状态等信息。
- docker images:列出本地的镜像。
- 例如:docker images,这将列出本地已经下载的所有镜像,包括镜像 ID、标签、大小等信息。
- docker pull:从远程仓库拉取镜像到本地。
- 例如:docker pull nginx:latest,这将从 Docker Hub 拉取最新版本的 Nginx 镜像到本地。
- docker build:基于 Dockerfile 构建镜像。
- 例如:docker build -t myimage:1.0 .,这将根据当前目录下的 Dockerfile 构建一个名为 "myimage" 版本号为 "1.0" 的镜像。
- docker stop:停止一个正在运行的容器。
- 例如:docker stop mycontainer,这将停止名为 "mycontainer" 的容器。
- docker start:启动一个已经停止的容器。
- 例如:docker start mycontainer,这将启动名为 "mycontainer" 的已经停止的容器。
- docker rm:删除一个或多个容器。
- 例如:docker rm mycontainer,这将删除名为 "mycontainer" 的容器。
7.3、docker的数据卷
Docker 的数据卷(Volume)是一种持久化存储数据的机制,可以在容器之间共享数据或者将数据持久化到宿主机上。使用数据卷可以解决容器中数据持久化和共享的问题,同时也提供了更好的数据管理和备份能力。
7.4、docker的默认网络模式有哪些
Docker 中常见的默认网络模式:
- bridge 模式:
- 这是 Docker 默认使用的网络模式。在这种模式下,每个容器都会分配一个唯一的 IP 地址,并且可以通过容器名称或者 IP 地址相互通信。如果没有显式指定网络模式,那么 Docker 会自动使用 bridge 网络。
- host 模式:
- 在这种模式下,容器和宿主机共享同一个网络命名空间,容器将直接使用宿主机的网络接口。这样可以获得最佳的网络性能,但同时也可能带来一些安全隐患。
- none 模式:
- 在这种模式下,容器拥有自己的网络栈,但是不进行任何配置。这意味着容器无法直接访问外部网络,也无法被外部网络访问。这种模式通常用于一些特殊的网络场景,如只需要本地通信的容器。
7.5、什么是Docker Compose
Docker Compose 是一个用于定义和运行多个 Docker 容器应用的工具。通过一个单独的 docker-compose.yml 配置文件,可以定义整个应用的服务、网络配置、数据卷等,并使用一个命令来启动、停止或管理整个应用。
8、git相关
8.1、git本地仓库和远程仓库的区别
这两类仓库在平时开发也是必不可少的
- 本地仓库是存储在计算机本地的Git仓库,用于保存项目的完整历史记录和文件版本。可以进行开发、修改和提交代码等git控制的操作。
- 远程仓库是位于网络上的Git仓库,通常托管在远程服务器上,如GitHub、Gitee、GitLab等。它用于协作和共享代码,团队成员可以将本地仓库的更改推送到远程仓库,或者从远程仓库拉取最新的更改到本地仓库。
8.2、git基本的工作原理是什么
Git的主要作用就是跟踪和管理项目文件的变化,记录文件的每个版本和修改。这里面有三个概念来进行控制
- 工作区:包含.git文件夹的目录就是工作区,也称为工作目录,主要用于存放开发的代码
- 版本库:前面看到的.git隐藏文件夹就是版本库,版本库中存储了很多配置信息、日志信息和文件版本信息等
- 暂存区:.git文件夹中有很多文件,其中有一个index文件就是暂存区,也可以叫做stage。暂存区是一个临时保存修改文件的地方
8.3、如果使用git产生了冲突,你是怎么解决的?
好的~
我们团队开发,当拉取代码的时候,如果有其他同事也跟我一样修改了同一个类中的相同位置的代码就有可能会发生冲突,解决冲突的第一时间我会先找对应的同事进行沟通,这些冲突一般都是前期沟通不充分导致的,通过沟通确定是什么问题。
解决冲突操作一般会使用idea来完成,当拉取代码的时候,如果有冲突会弹窗进行提示,主要是会做版本的比对,有本地的代码和远程仓库的代码,然后根据实际情况选择即可,最终解决冲突需要commit
如果不用idea,当执行pull命令的时候,也有可能会产生冲突,解决方案是
- 首先使用git status来查看哪些文件冲突
- 找到这些冲突的文件,在文件中会有冲突代码的标记,也是两部分:本地仓库的代码和远程仓库的代码
- 然后根据实际情况,进行删除多余的代码和标记即可
- 解决完冲突以后,需要使用git add来标记已解决冲突
- 完成所有的冲突解决后,需要使用git commit命令来提交修改,如果需要推送,可以直接git push
8.4、你们项目中分支是如何管理,创建分支有什么规则?
我们项目的分支主要有 master、 release、各种 develop,其中 develop 指的是开发过程中,每个版本根据需求实际情况, 创建一个或者多个分支,当需求开发完成以后,合并到其中一个分支,当本次需求上线后,在保证与线上代码一致的情况下, 将上线分支合并到 release并打上 tag 标签,记录版本信息,最后将release 再合并到 master, master 和 release 基本上不做修改。
- 分支名称有4段组成,格式如下:
dev-分支主名称-版本-日期
分支主名称 命名一般是模块名或者需求的简单描述,尽量做到见名知意, 后期如果需要查找旧版本信息, 相对也会比较容易查找.
9、maven相关
9.1、maven 用来做什么
Maven 是一个流行的项目管理工具,主要用于 Java 项目的构建、依赖管理和项目信息管理。以下是 Maven 的主要用途:
- 项目构建:
- Maven 可以帮助开发者对 Java 项目进行自动化构建。通过 Maven 的约定优于配置的原则,开发者只需定义项目的基本结构和依赖关系,Maven 就可以自动完成项目的编译、测试、打包等构建工作。
- 依赖管理:
- Maven 通过中央仓库和本地仓库来管理项目的依赖库。开发者可以在项目的配置文件中声明所需的依赖,Maven 将自动下载并管理这些依赖库。
- 项目信息管理:
- 通过 Maven,开发者可以方便地管理项目的元数据信息,如项目名称、版本号、作者、许可证等。这些信息可以被用于生成项目文档、发布到中央仓库等操作。
- 项目报告:
- Maven 提供了丰富的插件机制,可以生成各种项目报告,如单元测试报告、代码覆盖率报告、静态代码分析报告等,帮助开发者更好地了解项目的状态。
- 项目部署:
- Maven 可以帮助开发者将构建好的项目部署到指定的环境中,如本地、测试、生产环境等。
9.2、maven的规约说一下
- /src/main/java/ :Java 源码。
- /src/main/resource :Java 配置文件,资源文件。
- /src/test/java/ :Java 测试代码。
- /src/test/resource :Java 测试配置文件,资源文件。
- /target :文件编译过程中生成的 .class 文件、jar、war 等等。
- pom.xml :配置文件
9.3、Maven的生命周期
Maven 生命周期按照构建过程分为三个部分,即 清理(clean)、构建(build) 和 站点生成(site)。每个部分包含不同的阶段(phase),执行的顺序是固定的,也就是说 Maven 在执行构建时会依次运行每个阶段。
以下是 Maven 的生命周期和各个阶段的简要说明:
- 清理生命周期:
- pre-clean:在清理之前执行的动作
- clean:清理上一次构建生成的文件
- 构建生命周期:
- validate:验证项目是否正确并且所有必要信息都可用
- compile:编译项目的源代码
- test:测试编译后的代码
- package:将编译后的代码打包成可发布的格式,如 JAR、WAR 等
- install:将打包好的代码安装到本地仓库,方便其他项目进行依赖管理
- deploy:将打包好的代码部署到远程仓库,方便其他人使用
- 站点生命周期:
- pre-site:在生成站点之前执行的动作
- site:生成项目的站点文档
- post-site:在生成站点之后执行的动作,如部署站点到服务器上
- site-deploy:将生成的站点部署到远程服务器上