今天上午把一个简单的智能旅行助手项目跑通了,通过注册一些服务,获取access key,安装依赖,跑通了前后端,之后把衣服洗了一下。
下午收到久远银海offer了,明天准备入职,需要完成一些入职办理。
下午还有一个线上面式多益网络,面的时间还是好长啊,整体给我的感觉就是我答得不是很好,问的比较细,只背八股显然是不能应对的,比如其中一个实现了读写分离,但是主从库之间同步有延迟,改怎么解决,正常情况下背过八股都知道是在更新过一段时间内,读也强制走主库,但是面试官问我具体怎么实现的,我当时懵了,因为我没有具体自己实现过,我认为这个也是使用sharding-jdbc框架提供的,可以进行一个配置,但是这个我确实不了解,最后面式结束之后,问了一下豆包,说可以在代码层实现,具体流程如下:
- 自定义@Master注解;
- 我们需要重写sharding-jdbc框架的方法,重写获取数据源的方法;
- 使用aop扫描带有@Masterz注解的方法,之后切换数据源到主库,这样就可以实现自己配置强制走主库;
- 之后我们只需要在那种强一致性的读方法上加上@Master注解,比如支付后的订单查询等,这种强一致性,不能有延迟;
之后还问了缓存穿透的方式,我只答了什么是缓存穿透,以及一种方式,比如多次请求数据库中根本不存在的数据,那么显然每次请求都会直接打到数据库,但是他问我还有没有其他方式,我感觉我回答的这个比较笼统吧,但是最后原理肯定是这样的,更多的是首先对请求的基本格式进行一个校验,之后对于专门制造的数据,我们可以使用布隆过滤器来进行过滤。
之后就是问我的agent项目,由于这个项目我理解的还不是很透彻,导致面试官问我这个项目时,我回答的也不是很好,基本说没有自信,面试官一质疑,我就慌了,不知道的只好说不知道,不敢去编,主要问了我这个项目的工作流,我二次开发做了哪些工作,我答得也是一塌糊涂,还是面式前没有准备好,之后就问了rag,我大概是了解rag的,增强检索生成,让大模型回答可以根据特定场景,通过增加外部知识库,让LLM具有特定方面的知识,他问了我大模型和rag是如何进行通信的,需要把知识库全部喂给LLM吗?我肯定知道是不能的,但是我不知道他们如何通信的,我不敢回答通过配置的,因为我前面很多都是说通过配置,这里我就说不知道了,其实也就是首先我们把知识库存进一个知识向量数据库,之后拿到一个询问时,我们同样的使用相同embedding方式,将询问进行分片得到向量,之后通过向量数据库提供的SDK,将询问传进去,还可以设置一个top-k参数,会返回与我们询问向量最近的k个向量,之后我们把这k个向量和询问都同时喂给LLM,让LLM根据提供的知识库进行回答,这样就可以避免因为LLM不知道的特定场景下的规则出现幻觉,乱回答。
之后还问了算法方面的知识,问了我堆、快排等。
堆的话确实在算法比赛中使用最多的一般就是可以快速动态获取最大值和最小值,然后还有一个就是实现对顶堆,可以求一个序列的中位数,这个我倒是没有记错,因为这道题是我自己做过的,还有一些其他的应用场景,比如说:
- 求top-k的元素;
- 优先级队列,任务队列,规划调度,根据设置的优先级进行调度;
- 我知道的还可以用在哈夫曼编码上面,可以做到压缩文本,因为哈夫曼树就是每次找到两个词频最小的元素,然后向上建树,这个是我自己实现过的,所以以后遇到一定要说;
快排问了我实现原理,我说就是一个递归的过程,每次选择一个基准,然后实现让左侧所有元素小于基准,右侧所有元素大于基准,之后递归左边和右边;优化的话就是随机选择基准值,这样可以减小复杂度退化到\(O(n^2)\)的几率,比如说开始就是单调不增的,那么时间复杂度就会退化,也就是处理那种元素被随机打乱的序列,一般都可以做到\(O(n\log{n})\)的复杂度。
快排竟然还问我是否可以用到链表上,我凭印象说不可以,说快排需要连续空间,而链表一般不是连续空间,需要指针维护前后关系,所以不能,但是问豆包却说可以,但是显然这样维护指针更加麻烦,所以实际是可以的,但是不建议这样做。
之后还问了LRU算法,Least Recently used,最近最少使用算法,是一种缓存淘汰策略,具体实现如下:
我们规定一个缓存大小,比如说是k,使用到的数据结构双向链表、哈希表,哈希表存储每个key对应的地址,这样可以使用\(O(\log{n})\)找到key对应的节点,比遍历链表更快,双向链表主要是为了增加节点和删除节点。链表头的节点是热点数据,链表尾的数据是最少使用数据。
- 查询key:
- 如果key存在,取出元素,将这个节点移动到链表头;
- 如果这个key不存在,返回空;
- 写入key:
- 如果key不存在,那么将这个节点放在链表头部,同时如果容量达到上限k,那么我们移除链表尾节点;
- 如果key存在,那么更新值,将这个节点移动到链表头部;
这道题好像Leetcode上面是有的,但是我没有刷过这道题,所以只是大概了解,这样补全了这个算法。
之后就问了一些408的知识点,比如:
- 线程和进程的区别;
- 线程的通信方式,如何控制多线程资源;
- 进程间是如何通信的;
第二个我知道的是可以使用共享变量,但是对于竞争资源需要加互斥锁、或者条件变量、读写锁、信号量、任务队列;
第三个主要是通过:
- 共享内存;
- 管道;
- 信号量;
- Socket;
对了还有一个基础,tcp和gttp的区别,我靠,这道题我简直是乱答,竟然说tcp是面向连接的,是可靠的,http不是不安全的,我靠我当时主要是说http没有加密,所以不安全。
其实这道题主要区别在于tcp是传输层协议,面向连接;
而http是应用层协议,是基于tcp协议实现的,http协议主要是包装一下请求格式信息,定义请求方法 GET/POST、状态码、Header、Body等。
