关于java:搞定面试官系列字节面试官的灵魂三问为什么Redis这么快怎样支撑高并发如何解决并发竞争问题

前言


Redis是以后煊赫一时的NoSQL数据库,简直曾经成为高并发、高可用零碎的标配了。若是对Redis响应快的认知仅仅停留在基于内存和单线程的层面,恐怕是很难斩获大厂的Offer。本篇重点全面介绍Redis的单线程模型及如何撑持高并发的。

1 Redis齐全基于内存


Redis可能撑持高并发的第一个重要的起因就是齐全基于内存,这在很大水平上防止了诸如MySQL等关系型数据库须要频繁的磁盘I/O(磁盘I/O的寻道工夫、旋转提早、传输工夫等很耗时,皆是ms级的开销,而基于内存根本都是ns级的开销,齐全不是一个数量级)。

2 Redis的线程模型


2.1 阻塞式I/O模型Blocking I/O

说到I/O模型,大家肯定能想到传统意义上的Blocking I/O,该模型的工作形式是:当对某一个文件描述符(File Descriptor,以下简称FD)读写时,如果以后FD不可读或不可写,则不会对其它过程的操作做出响应,导致整体服务不可用。

文件描述符:在模式上是一个非负整数。实际上它指向内核为每一个过程所保护的该过程关上文件的记录表。

2.2 I/O多路复用

在 I/O 多路复用模型中,最重要的函数调用就是 select,该办法的可能同时监控多个文件描述符的可读可写状况,当其中的某些文件描述符可读或者可写时,select 办法就会返回可读以及可写的文件描述符个数。

2.3 Redis的单线程模型

Redis外部应用文件事件处理器File event handler,该处理器是单线程的,所以Redis才叫做单线程模型。它采纳 I/O 多路复用机制同时监听多个 Socket,依据 Socket上的事件来抉择对应的事件处理器进行解决。Redis服务采纳Reactor的形式来实现文件事件处理器,如下图所示:

综上剖析,Redis撑持高并发的第二个起因就是基于非阻塞式的I/O多路复用机制,是单线程模型,这在很大水平上防止了多线程频繁上下文切换的耗费。

3 Redis丰盛灵便的数据类型


Redis提供了string、hash、list、set、sorted set五种根本数据结构,并且还蕴含了HyperLogLog、Pub/Sub等多种扩大的优良数据结构。
Redis中数据结构不仅仅是丰盛,浏览源码你还会发现,设计也很奇妙很灵便,如string底层不同于C语言的实现,而是通过一种SDS(Simple Dynamic String)构造实现的,实质上是一个带长度信息的字节数组。这里少侠以字典hash为例,介绍Redis是如何做到疾速响应的。

3.1 hash内部结构

Redis中的hash和Java中的HashMap简直一样,都是通过分桶的形式存储元素并解决hash抵触,第一维是数组,第二维是链表,如下图所示,数组中保留的是链表中第一个元素的指针。

3.2 hash函数的抉择

在介绍Redis的hash函数前,少侠想先引入一个概念:hash攻打,简而言之,就是因为hash函数具备偏差性,黑客会依据这种偏差性进行攻打,导致hash的链表长度极不平均,甚至所有的元素都集中到一个链表,最终会导致查问性能急剧下降(从O(1)进化到O(n))。

那么Redis如何设计hash函数的呢?不同于Java中的hash算法,Redis实际上采纳了一种称为siphash算法,这个算法是兼顾了随机性和性能的后果。

3.3 渐进式rehash

说到hash,不可避免的就是扩容,然而Redis是单线程的,并且一些热点数据频繁被申请,如果此时扩容Redis很难接受这样的耗时过程。所以Redis采纳了渐进式rehash策略。
渐进式rehash会在rehash的同时,保留新旧两个hash构造,如下图所示,查问时会同时查问两个hash构造,而后会在操作指令(hget,hdel)中实现数据迁徙,然而如果客户端始终没有命令来触发此类操作,Redis会在定时工作中被动对hash进行数据迁徙。

4 Redis如何解决并发竞争问题


  • 客户端加锁(ReentrantLock或synchronized),但此形式只限于单机加锁,无奈解决分布式系统的并发竞争问题。
  • 乐观锁(redis 的命令 watch):
    当执行多键值事务操作时,Redis 不仅要求这些键值须要落在同一个 Redis 实例上,还要求落在同一个 slot 上,所以 redis 的事务比拟鸡肋,不过能够想方法遵循 redis 外部的分片算法把设计到的所有 key 分到同一个 slot。
  • redis 的 setnx 实现分布式锁:
    要设置超时工夫,避免抢占到锁的客户端因失败、解体或其余起因没有方法开释锁而造成死锁。

小结


Redis为何这么快其实是个涉及面很宽泛的问题,面试者如果仅仅停留在基于内存和多路IO复用这些概念层的了解,在面试中是要吃亏的。纯熟使用,深刻原理能力在面试中斩获佳绩。

我是少侠露飞,酷爱技术,酷爱分享。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理