Redis快速的原因

Redis 有哪些知识点

高可靠:主从复制、哨兵节点、持久化
高性能:数据结构、网络架构、持久化、线程模型
高可扩展:数据分片、负载均衡

Redis基础架构和重要模块

  1. 访问框架
    1. 网络访问
  2. 操作模块 get/set/delete
  3. 索引模块 基于哈希表
  4. 存储模块
    1. AOF
    2. RDB
      5。高可用:主从复制、哨兵机制
  5. 高可扩展:数据分片

Redis 快速的原因之高效的数据结构

String–> SDS 简单动态字符串
List --> 双向链表、压缩列表
Hash --> 哈希表、压缩列表
Sorted Set --> 跳表、压缩列表
Set --> 哈希表、整数数组

redis键和值是使用哈希表进行组织的。涉及到哈希冲突,解决是拉链法解决。当元素等于哈希表大小时进行rehash。

rehash:默认使用两个全局的哈希表。哈希表1和哈希表2,一开始使用哈希表1,扩容时使用哈希表2.

rehash三步:1. 给哈希表2分配更大的内存,哈希表1的二倍。2. 渐进式的将哈希表1数据移动到哈希表2 3. 是否哈希表1的内存

渐进式rehash:每一次请求都会拷贝一个索引位置的数据到哈希表2.通过一个从投开始的索引id实现。


整数数组和双向链表:基本查询复杂度是o(n) 顺序的读写
压缩列表:表头有三个字段zlbytes、zltail、zllen. 表示列表长度和链表尾偏移量和entry个数。表尾还有zlend。查询头部和尾部元素时间复杂度o(1) 其它的就是
o(n)

跳表:在有序链表的基础上,增加了多级索引。可以通过索引快速定位到元素,查找时间复杂度为o(log n)

时间复杂度的计算:
查找时间复杂度是需要访问的元素的个数。由每几个元素抽一个索引和索引的层数决定。前者是一个常数可忽略。后者计算: 假设俩个节点抽一个索引,第一层为n/2 第二层为n/4 第h层就是 n/2^h = 2. h=logn-1 时间复杂度就是2*h o(logn)

插入时间复杂度:数据量大时俩个节点抽一个,可用认为是一半的节点作为第一层索引,也就是说每个节点有1/2的概率有第一层索引。
插入只是通过一个计算函数随机生成插入到第几级索引。

计算函数代码 定义一个int遍历表示层数。通过Math.random()生成随机值。如果大于晋升的概率也就是1/2则层数加1.
这样第一层概率为1/2 第二层概率为1/4.并且需要设置最大层数。
这样下来插入的时间复杂度就是o(1).最坏每层都要插入则为logn
删除也是o(logn).

为什么单线程的 Redis 能那么快

redis单线程主要指的是网络io和键值对读写。还有其它线程,持久化、异步删除、集群数据同步等
1. 多线程在前期会增加速度,但是后期会因为访问的共享资源的同步问题导致效率下降。也就是并发控制问题
2. redis是在内存上面的,且用的高效数据结构
3. redis提供了多路复用机制,解决网络io的问题

网络io问题:如果只是一个线程执行一个网络,那么网络io的阻塞也会影响redis读写。accept()如果一直未建立连接就会阻塞,并且读数据的时候也会阻塞
解决:在阻塞点,先让redis做其它事情,等待阻塞等待的事件到达之后通知redis。Linux的IO多路复用机制

IO多路复用:只允许一个线程下,允许内核中存在多个监听套接字和已连接的套接字。
一个连接请求进入,FD监听套接字会将请求对应的事件放入事件队列中,之后基于事件回调机制处理改事件。就是有什么事件就调用redis对应的
处理函数。比如一个连接请求就会调用连接事件Accpet,然后内核就会调用redis的accpet函数。
io多路复用就是相当于医院的分诊台。有事件才会通知线程去处理。

你可能感兴趣的:(数据库,redis,数据结构,缓存)