面试第三期

面试题第三期

1.为什么选用redis代替session
  1. 在分布式环境下,用户的请求可能会被负载均衡到其他的服务器,从而导致无法获取之前的session,要在多台服务器上共享session实现数据同步,会增加系统的复杂性,此时考虑使用redis会更好

  2. 在项目中我采用了hash的类型来存储token,此时token作为外部键的一部分,用户信息作为值,设置了过期时间为30分中。同时利用拦截器对过期时间进行续期。

  3. redis的读取速率要高于session适合高频访问的业务场景,而我的项目中有优惠劵的秒杀业务就很适合。

2.Transactional失效的场景
  1. Transactional只适用于public方法

  2. 自调用,没有通过spring代理绕过了事务拦截器,解决方法有通过依赖注入自身来解决,或者获取代理对象

  3. 抛出除了 RuntimeExceptionError的其他异常,此时可以通过给transactional注解配置异常类型来解决

  4. 未启用事务注解或者数据库存在多数据源

  5. 在内部捕获了异常却没有抛出

3.你知道redisson的那几种锁
  1. 可重入锁,同一个线程可以多次获取同一把锁,不会造成自己把自己锁到外面的情形

  2. 红锁,同时向多个redis节点申请锁,只有超过半数的锁被释放才会真正的释放,可以利用redis集群来实现

  3. 联锁,红锁的低配版,只有所有的锁被释放才算真正的释放

  4. 公平锁,先到的线程会先拿到锁

4.redisson的看门狗

你可以把它看成一个锁的保镖,假如现在你有一个业务需要执行40秒,锁默认30秒的过期时间,此时看门狗每隔过期时间的1/3时间会检查一次,如果锁还被持有就会续期,直到释放锁。要想看门狗生效不能设置固定的过期时间,当锁释放或者线程结束时看门狗也会自动生效。

5.cookie,session,token的区别

Cookie 是存储在用户浏览器端的一个小型数据文件,用于跟踪和保存用户的状态信息。

主要用于保持用户登录状态、跟踪用户行为、存储用户偏好等。

存储在浏览器端

Session:

Session 是服务器端保存用户状态的机制,每个用户会话都有一个唯一的 Session ID。

主要用于跟踪用户在服务器上的状态信息,例如登录状态和购物车内容。

存储在服务器端,然后对应的 Session ID 通过 Cookie 保存在客户端浏览器中。

Token:

Token 本质是一种加密的字符串,用于身份验证和授权,可以包含用户信息和权限,用于验证用户身份或授权访问资源。

认证后,后端服务会返回 Token,存储在客户端(浏览器或移动应用中),后续客户端访问服务端需要带上这个 Token。

它们之间使用场景区别:

  • Cookie:主要用于客户端状态的简单存储和追踪。
  • Session:用于服务器端的复杂状态管理,特别是在需要存储大量会话数据时。
  • Token:用于无状态的认证和授权,特别是在分布式和跨域环境下。

简单来说,Cookie 和Session 更适合用于单次会话的认证和状态管理,而 Token 更适合用于跨会话的认证和状态管理。

6.跳表

现在有一个十分长的链表,你想要查询某个数据,你需要遍历来查找它,此时时间花费会很大,聪明的你想到了如果链表已经有序了,我们在众多节点里边挑选几个作为类似索引的东西,每当你查询时我们比对一下就可以缩小区间来加快速度。此时聪明的你又又又想到了,如果我查找的数据特别靠后,抽取的节点还是太多怎么办,这时候我们将原来抽取的节点再进行一次抽取,形成一个更广泛的索引便可迅速定位到对应区间。

7.为什么 Redis Zset 用跳表实现而不是红黑树?B+树?

1)相比红黑树而言实现简单

跳表基于多层链表实现,通过概率算法动态生成索引层级,没有左旋右旋等操作,逻辑理解上更为简单。而红黑树需要复杂的平衡操作(旋转)来维护结构,代码实现复杂度较高,理解门槛更高。

2)范围查询更高效

范围查询跳表可以通过 O(logn) 的时间复杂度定位起点,然后在原始的链表中往后遍历即可。

红黑树从结构上不支持范围查询。

3)结构更灵活

跳表的层数和节点结构是动态的,可以基于概率分布调整层数,灵活的适应不同的数据量(数据量大层级可以多一些,小的话层级少一些)。

红黑树则无法调整。

8.mvcc

MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种并发控制机制,允许多个事务同时读取和写入数据库,而无需互相等待,从而提高数据库的并发性能。

在 MVCC 中,数据库为每个事务创建一个数据快照。每当数据被修改时,MySQL 不会立即覆盖原有数据,而是生成新版本的记录。每个记录都保留了对应的版本号或时间戳。

多版本之间串联起来就形成了一条版本链,这样不同时刻启动的事务可以无锁地获得不同版本的数据(普通读)。此时读(普通读)写操作不会阻塞。

写操作可以继续写,无非就是会创建新的数据版本(但只有在事务提交后,新版本才会对其他事务可见。未提交的事务修改不会影响其他事务的读取),历史版本记录可供已经启动的事务读取。

相关推荐
京东零售技术28 分钟前
我在618主场,和3位顶尖技术博士聊了聊
面试
Java致死1 小时前
面试-操作系统
面试·操作系统
gufs镜像2 小时前
Swift学习总结——使用Playground
前端·ios·面试
Yrrr14 小时前
Redis 持久化机制详解:RDB、AOF 原理与面试最佳实践(AOF篇)
数据库·redis·面试·职场和发展
岁忧5 小时前
(LeetCode 每日一题) 2016. 增量元素之间的最大差值 (数组)
java·c++·算法·leetcode·职场和发展·go
晴殇i5 小时前
3 分钟掌握图片懒加载核心技术:面试攻略
前端·面试·trae
前端小巷子6 小时前
跨标签页通信(四):SharedWorker
前端·面试·浏览器
周壮7 小时前
03 面试官考察与 CAP 有关的分布式理论
分布式·面试