Redis为什么这么快?

Redis接收到一个键值对操作后能以微秒级别的时间找到数据,并完成操作。那他为什么这么快呢?

一、存储位置

    首先就是因为redis是一个内存型数据库,其数据是存在内存中的,所以读取速度比存在磁盘中的数据不是快了一星半点。

    不过这是用他的安全性换了的,因为一旦redis所在的服务器宕机或者断电,其内存中的数据就会丢失,这就是redis为什么需要RDB和AOF的原因了。

二、 键值对的数据结构

    另一大原因就是他的数据结构了。全局哈希表和为了解决冲突的rehash

          1)全局哈希表

    为了实现快速访问,redis采用了一个全局哈希表来存储所有的键值对。如上图所示,

    哈希表即一个数组,里面存储的是“哈希桶(entry)”,每当存储一个键值对时,会根据key进行hash计算,得到他在全局哈希表的位置,然后生成一个entry存入其中。entry中包含*key和*value, 其中*key为存入键值对的key,然而*value则是指向值的指针。

    因此,当你想要从redis中定位到一个值,只需要根据key找到“哈希桶”的位置,然后根据*value指针找到对应的值,无论redis有10条数据还是10000条数据,都只需要一次即可找到想要的数据,时间复杂度为O(1)。

    2)哈希冲突和rehash

    然而真的有这么简单吗?当然不是,你会发现随着数据的增多,redis的查询速度会越来越慢,这是为什么呢?主要是因为 “哈希冲突”:

   Redis中的全局哈希表的大小不可能是无限大的,当数据量很大时,两个 key 的哈希值和哈希桶计算对应关系时,正好落在了同一个哈希桶中, 这就是哈希冲突。 Redis 解决哈希冲突的方式,就是链式哈希。链式哈希也很容易理解,就是指同一个哈希桶中的多个元素用一个链表来保存,它们之间依次用指针连接。如下图所示:

    

     entry1、entry2 和 entry3 都需要保存在哈希桶 3 中,导致了哈希冲突。此时,entry1 元素会通过一个*next指针指向 entry2,同样,entry2 也会通过*next指针指向 entry3。这样一来,即使哈希桶 3 中的元素有 100 个,我们也可以通过 entry 元素中的指针,把它们连起来。这就形成了一个链表,也叫作哈希冲突链。

    当哈希冲突链上越来越长时,想获取冲突链上数据的时间也就越来越长,这就是前面提到的当数据量越来越大时,获取数据就越来越慢的原因。

    这样致命的问题,Redis当然不会允许他的出现,接下来就要说解决哈希冲突链的方法“rehash”,rehash 也就是增加现有的哈希桶数量,让逐渐增多的 entry 元素能在更多的桶之间分散保存,减少单个桶中的元素数量,从而减少单个桶中的冲突。那具体怎么做呢?

    其实,为了使 rehash 操作更高效,Redis 默认使用了两个全局哈希表:哈希表 1 和哈希表 2。一开始,当你刚插入数据时,默认使用哈希表 1,此时的哈希表 2 并没有被分配空间。随着数据逐步增多,Redis 开始执行 rehash,这个过程分为三步:给哈希表 2 分配更大的空间,例如是当前哈希表 1 大小的两倍;把哈希表 1 中的数据重新映射并拷贝到哈希表 2 中;释放哈希表 1 的空间。到此,我们就可以从哈希表 1 切换到哈希表 2,用增大的哈希表 2 保存更多数据,而原来的哈希表 1 留作下一次 rehash 扩容备用。

    这个过程看似简单,但是第二步涉及大量的数据拷贝,如果一次性把哈希表 1 中的数据都迁移完,会造成 Redis 线程阻塞,无法服务其他请求。此时,Redis 就无法快速访问数据了。为了避免这个问题,Redis 采用了渐进式 rehash。如下图所示

    简单来说就是在第二步拷贝数据时,Redis 仍然正常处理客户端请求,每处理一个请求时,从哈希表 1 中的第一个索引位置开始,顺带着将这个索引位置上的所有 entries 拷贝到哈希表 2 中;等处理下一个请求时,再顺带拷贝哈希表 1 中的下一个索引位置的 entries。这样就巧妙地把一次性大量拷贝的开销,分摊到了多次处理请求的过程中,避免了耗时操作,保证了数据的快速访问。

三、总结

      本文中主要从redis找数据的方面讲了redis为什么他这么快,一是:因为数据存储在内存中,所以读取速度快,二是:采用了全局哈希表存储键值对,并采用了rehash的方式解决导致查询慢的哈希冲突问题。讲到这里我们已经知道Redis可以快速找到数据,那么找到数据了,还需要操作数据,那么Redis是怎么快速对数据进行操作的呢?请听下回分解。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值