面试第三期

面试题第三期

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 不会立即覆盖原有数据,而是生成新版本的记录。每个记录都保留了对应的版本号或时间戳。

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

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

相关推荐
DanyHope2 分钟前
LeetCode 两数之和:从 O (n²) 到 O (n),空间换时间的经典实践
前端·javascript·算法·leetcode·职场和发展
1张驰咨询116 分钟前
智慧城市交付困局:用六西格玛培训,将项目毛利从行业平均的12%提升至龙头水平的22%
人工智能·职场和发展·智慧城市·六西格玛
gis分享者22 分钟前
如何在 Shell 脚本中如何使用条件判断语句?(中等)
面试·shell·脚本·语法·使用·判断·条件
LYFlied1 小时前
【每日算法】LeetCode 114. 二叉树展开为链表:从树结构到线性结构的优雅转换
数据结构·算法·leetcode·链表·面试·职场和发展
Q741_1471 小时前
Linux 进程核心解析 fork()详解 多进程的创建与回收 C++
linux·c++·面试·笔试·进程
牛客企业服务1 小时前
AI面试:如何从概念真正落地?
人工智能·面试·职场和发展
铭哥的编程日记2 小时前
后端面试通关笔记:从真题到思路(me)
笔记·面试·职场和发展
写写闲篇儿11 小时前
微软面试之白板做题
面试·职场和发展
敲敲了个代码12 小时前
隐式类型转换:哈基米 == 猫 ? true :false
开发语言·前端·javascript·学习·面试·web
liang_jy12 小时前
Android LaunchMode
android·面试