我们都知道 , 在面试的环节中 , 会有各种千奇百怪的问题 , 最经典的就是各种数据库 , 这种中间件 , 还有就是底层原理 , 还有就是关于缓存数据库这块 , 今天了不起就来说说这个某东最喜欢问的一个内容 , 那就是关于 redis 的一些问题 , 比如 Redis 为什么快?
Redisredis是一个key-value存储系统 。
和Memcached类似 , 它支持存储的value类型相对更多 。
包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型) 。
这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作 , 而且这些操作都是原子性的 。在此基础上 , redis支持各种不同方式的排序 。与memcached一样 , 为了保证效率 , 数据都是缓存在内存中 。
区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件 , 并且在此基础上实现了master-slave(主从)同步 。
Redis 为什么快?
- 纯内存访问
- 单线程 , 避免上下文的切换
- 渐进式ReHash , 缓存时间戳
其实 Redis 快的原因 , 是因为 Redis 的内部 , 采用了很多效率高的机制 , 就比如我们说的第三个 , 渐进式的ReHash 和缓存时间戳 。
什么是渐进式 ReHash我们在开篇中也说了 , Redis是一个 key-value 存储系统 。
这样就不得不提一下另外的一个概念了 , 全局Hash表
为了实现从键到值的快速访问 , Redis使用了一个全局哈希表来保存所有键值对 。而一个 Hash 表 , 其实本质上就是一个数组 , 数组的每一个元素称为一个 Hash 桶 , 所以 , 这也是为什么很多人称 Hash 表是由多个 Hash 桶组成的 , 而每个 Hash 桶中保存了键值对数据 。

文章插图
图片
如果他们出现了 Hash 冲突了 , 那么就会使用连表的方式进行解决 。
一般的 , 当我们插入数据的时候 , 数组的长度不会很长 , 但是当我们在不断的往内部插入数据的过程中 , 就会扩容 , 比如我们扩容是N倍 , 这个时候就会涉及到我们原有数据元素的移动 , 而这个过程 , 我们流称之为 ReHash 了 。
但是随着移动 , 就会伴生出一些问题 , 比如我们的元素非常的多 , 上千条 , 甚至上万条 , 那么如果元素移动的话 , 一次性移动上千甚至上万条的时候 , 就必然的导致一种情况的出现 , 那都不用说 , IO阻塞了 , 因为元素的移动 , 就有可能导致我们的元素从1的位置 , 挪到了4的位置 , 甚至挪动到n的位置 , 数据只要移动 , 那么久一定会出现阻塞的问题 , 一旦开始阻塞了 , 那 Redis 的速度 , 必然会下降 。
所以为了解决这个阻塞的问题 , 所以为了解决这个问题 , 所以 Redis 使用的是渐进式的 ReHash 。
而这个渐进式的 ReHash 其实原理也不复杂 , 总结大白话就是把一次大量拷贝的开销 , 分摊到多次处理请求的过程中 , 避免耗时操作 , 保证数据的快速访问 。
那么他这个分摊请求是怎么处理的呢?
首先、Redis 默认使用了两个全局哈希表: 哈希表 1 和哈希表 2 。一开始 , 当你刚插入数据时 , 默认使用哈希表1 , 此时的哈希表 2 并没有被分配空间 。随着数据逐步增多 , Redis 开始执行 ReHash 。
