java面试宝典 redis和分布式锁

  • redis 是基于key-value的内存高速缓存数据库

  • redis 是单线程模型

  • redis 是单线程模型为什么能效率这么高?

  1. 纯内存操作
  2. 核心是基于非阻塞的 IO 多路复用机制Epoll,可以让单个线程高效的处理多个连接请求
  3. 单线程反而避免了多线程的频繁上下文切换问题
  • redis持久化

  1. rdb策略

rdb策略是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,用二进制压缩存储后再替换旧的镜像文件,

  1. aof策略

AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。

  • 实现 redis 的事务原子性

使用lua脚本,在lua脚本中执行的操作是原子性的,不过要注意redis在执行lua脚本时是不可以处理其他请求的

  • 如何让redis处理更大的并发量

redis 集群

  • redis的缓存穿透

缓存穿透是指查询一个数据库一定不存在的数据,因为查出来的数据是空,所以不会缓存数据,这样就导致了每次查询都会直接查询数据库

解决方案:

如果从数据库查询的对象为空,也放入缓存,只是设定的缓存过期时间较短,比如设置为60秒。

  • redis的缓存雪崩

缓存雪崩,是指在某一个时间段,缓存集中过期失效

解决方案:

  1. Key 缓存的周期带个随机因子,缓存失效时间点也分散开来
  2. 使用 缓冲调用 开源模块
  • redis的缓存击穿

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,导致数据库被压垮

解决方案:

  1. 根据缓存key业务特性设置缓存周期
  2. 使用 缓冲调用 开源模块
  • 基于redis实现的分布式锁

分布式锁

分布式锁是控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性

业务中对分布式锁的要求:
  1. 互斥性。在任意时刻,只有一个客户端能持有锁。
  2. 不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
  3. 具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。
  4. 解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。
Redisson

Redisson采用了基于NIO的Netty框架,不仅能作为Redis底层驱动客户端,具备提供对Redis各种组态形式的连接功能,对Redis命令能以同步发送、异步形式发送、异步流形式发送或管道形式发送的功能,LUA脚本执行处理,以及处理返回结果的功能,还在此基础上融入了更高级的应用方案,不但将原生的RedisHash,List,Set,String,Geo,HyperLogLog等数据结构封装为Java里大家最熟悉的映射(Map),列表(List),集(Set),通用对象桶(Object Bucket),地理空间对象桶(Geospatial Bucket),基数估计算法(HyperLogLog)等结构,在这基础上还提供了分布式的多值映射(Multimap),本地缓存映射(LocalCachedMap),有序集(SortedSet),计分排序集(ScoredSortedSet),字典排序集(LexSortedSet),列队(Queue),阻塞队列(Blocking Queue),有界阻塞列队(Bounded Blocking Queue),双端队列(Deque),阻塞双端列队(Blocking Deque),阻塞公平列队(Blocking Fair Queue),延迟列队(Delayed Queue),布隆过滤器(Bloom Filter),原子整长形(AtomicLong),原子双精度浮点数(AtomicDouble),BitSet等Redis原本没有的分布式数据结构。不仅如此,Redisson还实现了Redis文档中提到像分布式锁Lock这样的更高阶应用场景。事实上Redisson并没有不止步于此,在分布式锁的基础上还提供了联锁(MultiLock),读写锁(ReadWriteLock),公平锁(Fair Lock),红锁(RedLock),信号量(Semaphore),可过期性信号量(PermitExpirableSemaphore)和闭锁(CountDownLatch)这些实际当中对多线程高并发应用至关重要的基本部件。正是通过实现基于Redis的高阶应用方案,使Redisson成为构建分布式系统的重要工具。

Redisson 是如何实现分布式锁要求的
  1. 互斥性

线程A和线程B会在redis中竞争同一个key,哪条线程获取到key则执行业务,另一个线程自旋等待

  1. 不会发生死锁

线程A获取到锁后,会起一条守护线程,守护线程会给这个锁续时,所以如果线程A宕机了,守护线程没了,锁没有续时就会被回收到

  1. 具有容错性

redis 的主从配置

  1. 解铃还须系铃人

线程A 在redis获取key时,会给这个key一个当前线程的UUID,线程A 再次请求锁,由于UUID一样,则会再次获取到key, 并且key的计数器+1, 线程A 解锁,判断UUID,假如UUID 一致, key的计数器-1, 当计数器<=0 key就会被回收。

更多demo请关注

springboot demo实战项目
java 脑洞
java 面试宝典
开源工具

#公众号
五分钟了解前沿技术,大数据,微服务,区域链,提供java前沿技术干货,独立游戏制作技术分享

五分钟技术

如果这篇文章对你有帮助请给个star
image.png