(2023打卡)每日两道面试题|一道算法题|7月4日

(2023打卡)每日两道面试题|一道算法题|7月4日

1.面试题

1.1.缓存穿透

在这里插入图片描述

缓存穿透:查询一个不存在的数据,Mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库,导致宕机

**解决方案一:**缓存空数据,查询返回的数据为空,仍把这个空结果进行缓存

缺点实例:比如id为1的数据本来为null,但是后来添加了一条数据到Mysql,但是缓存中还是null,导致缓存和数据库中的数据不一致

**解决方案二:**布隆过滤器

在这里插入图片描述

bitmap(位图):相当于是一个以(bit)位为单位的数据,数组中每个单元只能存储二进制数0或1

**布隆过滤器作用:**布隆过滤器可以用于检索一个元素是否在一个集合中。

在这里插入图片描述

误判率:数组越小误判率就越大,数据越大误判率就越小,但是同时带来了更多的内存消耗。

优点:内存占用较少、没有多余key

缺点:实现复杂、存在误判

总结(缓存穿透):

  1. 什么是缓存穿透、怎么解决
    • 缓存穿透:查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库
    • 解决方案一:缓存空数据
    • 解决方案二:布隆过滤器
面试官:什么是缓存穿透?怎么解决?
什么是缓存穿透
查询一个一定不存在的数据,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到DB去查询,可能导致DB挂掉,这种情况大概率是遭到了攻击

解决方案
缓存空数据:给不存在的id赋值一个空数据,仍然把这个空数据进行缓存。

布隆过滤器:布隆过滤器主要是用于检索一个元素是否在一个集合中,我们当时使用的是redisson实现的布隆过滤器,
它的底层主要是先去初始化一个比较大的数组,里面存放的二级制0或1,在一开始都是0,当一个key来了之后经过3次hash计算。模于数组长度找到数据的下标然后把数组中原来的0改为1,这样的话,三个数组的位置就能标明一个key的存在,查找的过程也是一样的

1.2.缓存击穿

缓存击穿:给某一个key设置了过期时间,当key过期的时候,恰好这时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮

解决方案一:互斥锁

解决方案二:逻辑过期(不设置过期时间)

设置一个expire过期时间字段,使用它用于描述

在这里插入图片描述

总结(缓存击穿):

  • 缓存击穿:给某个key设置了过期时间,当key过期的时候,恰好这时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮
  • 解决方案一:互斥锁,强一致,性能差
  • 解决方案二:逻辑过期,高可用,性能优,不能保证数据绝对一致
面试官:什么是缓存击穿?怎么解决
缓存击穿是一个key设置了过期时间,在key的时间过期的同时,有大量并发的请求,请求这个key这个时候就会导致DB不堪重负,结果可能会宕机
有两种解决方案:
一互斥锁:当缓存失效时,不立即去load db,先使用redis的setnx去设置一个互斥锁,当操作成功返回时再进行load db的操作并回设缓存,否则重试get缓存的方法

二逻辑过期
1.不给指定key设置过期时间,取而代之的是给这个key新增一个expire(过期时间)字段
2.当查询时先从redis中取出数据,判断当前数据是否过期
3.如果过期则开通另外一个线程做数据同步,当前线程正常返回数据,这个数据不是最新数据

2.算法题

在这里插入图片描述

提示:

1 <= nums.length <= 300
1 <= nums[i].length <= 500
0 <= nums[i][j] <= 103

2.1.分析:

先将二维数组排序,得到从小到大的顺序,然后通过比对每列的大小确定最大值,最后加到一个结果变量中

class Solution {
    public int matrixSum(int[][] nums) {
    	//最后结果
        int res=0;
        //获取列数
        int m=nums.length;
        //获取行数
        int n=nums[0].length;
        for(int i=0;i<m;i++){
            //将每列中的的数组进行从小到大排序
            Arrays.sort(nums[i]);
        }
		
        for(int j=0;j<n;j++){
        	//每遍历完一列归零
            int maxVal=0;
            for(int i=0;i<m;i++){
            	//比较出一行中的最大值
                maxVal=Math.max(maxVal,nums[i][j]);
                //源码分析
                //public static int max(int a, int b) {
        			//return (a >= b) ? a : b;
    			//}
            }
            //最后加到返回的结果内
            res+=maxVal;
        }
        //返回结果
        return res;
    }
}

在这里插入图片描述

以上图为例,当排序完成之后nums二维数组则会是{{1,2,7},{2,4,6},{3,5,6},{1,2,3}},以上两个For循环,加上Math中的取最大值方法

对应的值会是

第一次遍历,需要注意的是这取的是每一列的值,仔细查看以下代码是先遍历j再遍历i
nums[0][0]=1
nums[1][0]=2
nums[2][0]=3
nums[3][0]=1
后面根据以上图片以此类推

 for(int j=0;j<n;j++){
     for(int i=0;i<m;i++){
         maxVal=Math.max(maxVal,nums[i][j]);

2.2.使用技术重点:

Arrays中的sort方法用于排序,Math中max用于找最大值,通过两个For嵌套得到以每列作为对比的,目的得出每次循环的结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jacob_uln

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值