【2024秋招】2023-9-16 贝壳后端开发一面

1 秒杀系统

1.1 如何抗住高并发

1.2 数据一致性你是怎么处理,根据场景来说明你的设计思路

1.3 你们当时系统的架构是怎么样的

秒杀表做节点隔离,

1.4 为了保证数据一致性,引入了redission的锁,你是为了抗住高并发而去为了引入这个锁还是说为了保证数据一致性去引入的

答:主要是为了抗住高并发问题,解决redis的缓存击穿问题,但是也能解决一定的数据一致性问题。

是的,当我们谈到“击穿”问题时,通常指的是缓存击穿,即当某个热点缓存失效时,大量的请求直接涌向底层存储系统(如数据库),可能导致该系统过载。

在这种情况下,引入 Redission 的分布式锁主要是为了抗住这种高并发,即防止大量请求直接涌向底层系统。具体做法是,当缓存失效时,第一个到达的请求获取锁并重新加载数据到缓存,而其他并发请求则需要等待该请求完成数据加载和缓存更新。一旦数据被加载回缓存,那么后续的请求就可以直接从缓存中获取,而不必再次访问底层系统。这样,即使有大量的并发请求,也只有少数请求真正访问底层系统,从而避免了系统过载的问题。

所以,确实,对于缓存击穿问题,引入 Redission 的分布式锁主要是为了应对高并发,保护底层存储系统不被过度访问。

1.5 为了应对缓存击穿,使用redission分布式锁,这里redission有对一致性上起作用吗

为了应对缓存击穿,使用 Redission 分布式锁是为了确保在缓存失效时,只有一个请求去加载数据并更新缓存,防止底层数据库被大量并发请求压垮。但这里的一致性问题也是相关的,尤其是确保正确的数据被加载到缓存中。

在这种场景下,Redission 的作用在一致性上体现在:

  1. 单点加载:分布式锁确保在某一时刻只有一个请求(或一个服务实例)能够去加载数据。这避免了不同的请求可能在微小时间差异内加载到不同版本的数据,并都尝试去更新缓存的情况。例如,考虑一个场景,在某个请求加载数据的过程中,数据在数据库中被修改,紧随其后的另一个请求可能会加载到新版本的数据。如果没有分布式锁,两个请求可能都会尝试更新缓存,导致缓存中的数据在短时间内频繁切换。

  2. 减少竞态条件:没有分布式锁的情况下,多个请求可能会并发地检测到缓存失效,并尝试从数据库加载数据并更新缓存。这可能会导致竞态条件,从而导致不可预测的结果。引入锁后,请求会按照顺序执行,消除了竞态条件,确保数据加载和缓存更新的操作是原子的。

综上所述,Redission 分布式锁在处理缓存击穿的问题时,不仅帮助我们抗住高并发,还确保了数据的一致性。

1.6 你引入缓存后,可以预减库存,那现在引入了一个新的问题,mysql和redis数据的一致性,你是如何保证的

答:库存回退时,就涉及到这个mysql和redis的多级库存回退问题,库存回退涉及到用户取消订单场景,一般是先更新数据库的商品表,然后再删除缓存;另一种策略是先使用redis延时双删的方法。

美团二面:Redis与MySQL双写一致性如何保证

1.7 从整体的架构来描述一下你的秒杀项目

2 mini-spring项目

2.1 讲一下你的迷你版spring项目

1 IOC的本质:spring容器管理IOC的生命周期
2 一些注解

3 一个bean如何托管到IOC容器中

4 spring循环依赖问题的解决

2.2 介绍一下你对AOP的理解

2.3 有没有相应的用到AOP的地方

1 鉴权,打印日志

2 aop解决单体架构下的超卖问题

3 mysql

3.1 mysql的事务以及可以解决的各种问题

3.2 你平常用到是哪一个隔离级别

4 redis

4.1 redis的过期策略

4.2 内存淘汰策略

5 算法

5.1 二叉树根节点到叶子节点的所有路径和

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param root TreeNode类
     * @return int整型
     */
    public int sumNumbers (TreeNode root) {
        // write code here
        getPathSum(root, 0);
        return res;
    }
    int res = 0;
    void getPathSum(TreeNode node, int s) {
        if(node==null)return;
      	s = s * 10 + node.val;
        if (node.left ==null&&node.right==null) {
            res += s;
            return;
        }
        getPathSum(node.left, s);
        getPathSum(node.right, s);

    }
}

6 反问

6.1 你们部门业务是什么

答:房客源啊,交易技术啊,签约交易,比如买卖二手房的合同,签约的过程,如何保证系统的稳定,数据的一致性,挑战还是比较大的;2B和2C的都会遇到,然后贝壳有活水策略,也没有什么负担

6.2 您这边买房,租房和二手都会有吗

答:对

你可能感兴趣的:(面经,贝壳,后端开发,2024秋招)