5.科大讯飞一面
-
Redis数据结构和缓存实现:
-
数据结构:
-
字符串(Strings):Redis中最基本的数据结构,用于存储简单的字符串、整数或者浮点数。
-
列表(Lists):实现了双向链表,可以用来存储一系列字符串。
-
集合(Sets):无序集合,元素唯一,可以用来存储不重复的字符串。
-
有序集合(Sorted Sets):类似于集合,但每个元素都会关联一个分数(score),可以根据分数排序。
-
哈希(Hashes):键值对集合,适合存储对象。
-
位图(Bitmaps):以位为单位进行存储,适用于布尔值存储。
-
超日志(HyperLogLogs):用于估计集合的基数,占用空间非常小。
-
地理空间(Geospatial):存储地理位置信息,可以进行半径查询等操作。
-
-
缓存实现:
-
缓存通常用于存储热点数据,减少数据库的访问压力。
-
实现方式通常是将数据读取和写入操作先作用于缓存,然后同步或异步更新到数据库。
-
-
缓存三兄弟问题及解决方案:
-
缓存击穿:大量请求访问一个不存在或过期的缓存键。解决方案:使用锁或设置热点数据永不过期。
-
缓存雪崩:大量缓存同时过期。解决方案:设置不同的过期时间,使用缓存预热。
-
缓存穿透:查询不存在的数据。解决方案:使用布隆过滤器,返回空值并设置过期时间。
-
-
-
Redis分布式锁实现:
-
使用Redis的
SETNX
命令尝试设置一个key,如果设置成功,则表示获取到了锁。 -
设置锁的过期时间,防止客户端崩溃后锁无法释放。
-
释放锁时,使用Lua脚本确保只有锁的持有者才能释放锁,避免误释放。
-
可以使用Redis的Redlock算法来提高分布式锁的可靠性。
-
-
HashMap底层原理和扩容原理:
-
底层原理:
-
HashMap基于数组和链表(或红黑树)实现。
-
通过hash函数计算key的hashCode,然后映射到数组的某个位置。
-
如果多个key的hashCode相同,这些key会形成一个链表,称为hash冲突。
-
当链表长度超过一定阈值时,链表会转换成红黑树,以提高查询效率。
-
-
扩容原理:
-
当HashMap中的元素数量达到容量和负载因子(load factor)的乘积时,会进行扩容操作。
-
扩容操作会创建一个新的更大的数组,并将旧数组中的所有元素重新哈希到新数组中。
-
-
-
JVM垃圾回收算法和回收过程:
-
垃圾回收算法:
-
标记-清除(Mark-Sweep):标记出所有活动对象,然后清除未被标记的对象。
-
标记-整理(Mark-Compact):标记活动对象后,将所有活动对象移动到内存的一端,清理掉边界以外的内存。
-
复制(Copying):将内存分为两个半区,每次只使用一个半区,在垃圾回收时,将活动对象复制到另一个半区。
-
-
回收过程:
-
标记阶段:遍历所有可达对象,标记它们为活动状态。
-
清除或整理阶段:清除未被标记的对象,或者在标记后移动活动对象。
-
-
-
JVM内存机制和对象垃圾判断:
-
内存机制:
-
程序计数器:记录当前线程所执行的字节码行号。
-
虚拟机栈:线程私有的,存储局部变量表、操作数栈等。
-
本地方法栈:为虚拟机使用到的Native方法服务。
-
堆:所有线程共享的内存区域,用于存放对象实例。
-
方法区(或元空间):存储已被加载的类信息、常量、静态变量等。
-
-
对象垃圾判断:
- 使用可达性分析算法,从GC Roots(如虚拟机栈中的引用、静态变量、常量池中的引用等)开始,如果一个对象无法通过任何引用链到达,则被认为是垃圾。
-
-
支付幂等性:
-
幂等性指的是多次执行同一操作,结果一致,不会因为多次执行而产生副作用。
-
在支付系统中,可以通过以下方式实现幂等性:
-
唯一事务号:为每次支付请求生成一个唯一的事务号,处理时检查事务号是否已存在。
-
状态机:维护支付请求的状态,确保每个状态只被处理一次
-
幂等接口设计:支付接口设计时保证多次请求不会导致重复支付。
-
消息队列:将支付请求放入消息队列,消费端保证消息的幂等性。
-
幂等数据库操作:使用数据库的事务机制或乐观锁保证数据库操作的幂等性。
-
-
八股文分类整理 老哥们点点赞,订阅一下,纯福利做数据。