redis学习(redis为什么快?)

1. 基于内存
2. IO多路复用
3. 单线程模型:避免上下文切换
4. 渐进式ReHash、缓存时间戳

基于内存

计算机硬件处理速度
在这里插入图片描述
mySQL数据库需要建立索引来加查询速度
另外
在这里插入图片描述

Redis 是基于内存的数据库,因此**数据存储在内存中**,这使得读写速度非常快。内存存储允许 Redis 在内存中直接进行数据操作,而不必像传统数据库那样频繁地进行磁盘 I/O 操作。

IO多路复用

io多路复用就是一种同步模型,它实现一个线程可以监听多个文件描述符,一旦某个文件描述符就绪,就能够通知应用程序,进行响应的读写操作。
在这里插入图片描述
首先会有一些客户端连接redis去创建socket套接字,会有文件事件处理器来处理请求,当有连接进来时,redis会创建于客户端对应的文件描述符,然后监听这些文件描述符,当一个或多个文件描述符有事件到来时,io多路复用就会处理描述符上的所有就绪事件,如使用epoll来返回就绪文件描述符列表,并处理就绪事件(使用单线程模型来处理),io多路复用会把就绪事件连接信息封装起来,放到一个队列发送给文件事件分发器,分发器根据事件类型,分发不同的事件到不同的处理器来处理,如:连接应答处理器处理连接事件等。

单线程模型

因为**CPU不是redis的瓶颈,redis的瓶颈是内存和网络带宽,单线程可以省去上下文切换的开销。
Redis 采用单线程模型,通过事件驱动的方式处理多个连接。这样可以
避免多线程之间的竞争条件,简化了数据访问的同步问题。尽管是单线程,但 Redis 通过非阻塞的 I/O 和事件循环来处理并发请求,使其在高并发环境下依然能够快速响应。
redis4.0:多线程处理非阻塞命令
redis6.0:
加入多线程IO处理网络IO性能瓶颈,IO读写是多线程,命令执行单线程**

渐进式ReHash、缓存时间戳

“渐进式 ReHash” 和 “缓存时间戳” 是两种优化 Redis 性能的方法。

全局哈希表
为了实现从键到值得快速访问,Redis采用了一个哈希表来保存所有得键值对。一个哈希表其实就是一个数组,数组下标的每个元素被称为哈希桶。所以一个哈希表由多个哈希桶组成,每个哈希桶保存了键值对的元素数据。
在这里插入图片描述

哈希冲突
既然Redis是哈希表,那必然会有哈希冲突,**Redis采用了链式哈希来解决哈希冲突,即一个哈希桶里面会有由多个元素用链表保存,它们之间用指针连接。但是如果数组长度一直不变化,元素哈希冲突越来越多,这个时候检索效率会大大降低,那么Redis就需要对数组长度进行扩容,**但是扩容后每个哈希桶的元素会分散在不同的位置,涉及到了元素的移动,那么必会造成阻塞IO。

  1. 渐进式 ReHash: Redis 使用哈希表来实现存储数据,而哈希表的大小在初始化时就已经确定。为了应对数据量变大时的情况,Redis 在哈希表达到一定负载因子时会触发 ReHash 操作,即创建一个更大的哈希表(X2),并将原有的数据重新散列到新的哈希表中。这个过程通常是阻塞的,会导致在 ReHash 过程中的一段时间内请求变慢。“渐进式 ReHash” 就是一种优化策略,它将 ReHash 操作分解为多个小步骤,在每个小步骤中处理一小部分数据,而不是一次性处理整个数据集。这样可以减小 ReHash 对性能的影响,使得 Redis 在进行 ReHash 的同时依然能够快速响应请求。
    注:如果旧表还没有完全同步到新表,新表却再次需要rehash了,怎么处理的呢?
    答:等到同步完到新表之后,再次同步
rehash时,进行扩容时,会进行判断

int dictExpand(dict *d, unsigned long size)
{
dictht n; // 新哈希表
unsigned long realsize = _dictNextPower(size); // 计算扩展或缩放新哈希表的大小(调用下面函数_dictNextPower())

/* 如果正在rehash或者新哈希表的大小小于现已使用,则返回error */
if (dictIsRehashing(d) || d->ht[0].used > size)
return DICT_ERR;
....
}
  1. 缓存时间戳: 缓存时间戳是指在 Redis 中缓存数据的同时,为每个缓存的数据记录一个时间戳。通过使用时间戳,可以实现对缓存数据的定期更新或重新加载,以确保缓存中的数据始终保持新鲜。
    时间戳的使用可以有效避免缓存中存储过期或失效的数据。当某个缓存数据的时间戳过老或达到一定的时间间隔时,系统可以触发重新加载或更新该缓存数据。这种方式能够提高数据的实时性,同时减少因为使用过期数据而引发的性能问题。
    平常中使用时间戳常常需要一次系统调用去获取系统的毫秒时间戳,但是作为单线程的Redis无法承受,因为每次去系统调用是比较费时间的,所以它需要对于时间戳进行一次缓存,由一个定时任务进行每毫秒更新时间戳,从而获取时间戳都是直接从缓存就取出

参考
https://www.bilibili.com/video/BV1u3411S7oS/?spm_id_from=333.337.search-card.all.click&vd_source=0cb0c5881f5c7d76e7580fbd2f551074
http://redisbook.com/preview/dict/incremental_rehashing.html
https://blog.csdn.net/qq_36701692/article/details/129320777

学习ing,如有错误,请指正,谢谢
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值