redis为什么查询速度这么快的原因(一)

笔记学习来源极客时间深入学习redis和自己总结
一.简单的kv nosql基础架构的构成
首先作者让我们从一个基础的nosql的架构让我们认识一个kv结构的nosql的基础架构,在基础架构中分为访问模式,基础操作,索引模块和存储模式(分配器和持久化)。
一个简单的kv nosql,在访问模式中分为本地库模式和网络访问模式(我认为的是client端口),基础的操作分为增删查,对应redis就是put delete get/scan,在redis中put和delete操作不但是更新和删除,还做了资源的分配和释放,索引模块主要是为了快速查询常见为b+树和hash表,存储模式这里是可以支持永久存储和内存存储还有分配内存和释放内存的机制。
 
二.对于redis为什么查询速度这么快的原因
在redis中主要的数据类型为String,set,list,hash,sortSet,在我看来这些数据类型都是比较节约内存的list和set都是因为是连续的内存无论在内存存储还是在获取到内存访问都是效率比较高的,原因是可以对下标进行随机访问时间复杂度为O(1)这个是在于数据层面为何能快速拿去数据的一部份。
第二个原因是的索引查询是用hash表进行搜索的,hash表中是一个list每个list中的一个单位为存储entry的单位,entry中存储了key和value,因为hash存储的原因如果在存入大数据量的时候难免会出现hash冲突,为了避免这个情况redis在储存相同hash时使用了hash链表进行存储,然后通过rehash,就是增加hash表中hash桶(就是list中的一个单位),然后把冲突的值全部拷贝过去。
在拷贝的过程中会遇到一个问题,因为redis是单线程,如果全部拷贝的话这样会产生阻塞这样的话可能无法运行,那么redis使用的是渐进式拷贝,就是逐个分配这样可以把冲突的hash分配到其他桶中这样访问效率可以更快,一下为redis底层数据类型。
作者给出4行口诀
单元素操作是基础;范围操作非常耗时;统计操作通常高效;例外情况只有几个。
第一,单元素操作,是指每一种集合类型对单个数据实现的增删改查操作。例如,Hash 类型的 HGET、HSET 和 HDEL,Set 类型的 SADD、SREM、SRANDMEMBER 等。这些操作的复杂度由集合采用的数据结构决定,例如,HGET、HSET 和 HDEL 是对哈希表做操作,所以它们的复杂度都是 O(1);Set 类型用哈希表作为底层数据结构时,它的 SADD、SREM、SRANDMEMBER 复杂度也是 O(1)。这里,有个地方你需要注意一下,集合类型支持同时对多个元素进行增删改查,例如 Hash 类型的 HMGET 和 HMSET,Set 类型的 SADD 也支持同时增加多个元素。此时,这些操作的复杂度,就是由单个元素操作复杂度和元素个数决定的。例如,HMSET 增加 M 个元素时,复杂度就从 O(1) 变成 O(M) 了。
第二,范围操作,是指集合类型中的遍历操作,可以返回集合中的所有数据,比如 Hash 类型的 HGETALL 和 Set 类型的 SMEMBERS,或者返回一个范围内的部分数据,比如 List 类型的 LRANGE 和 ZSet 类型的 ZRANGE。这类操作的复杂度一般是 O(N),比较耗时,我们应该尽量避免。不过,Redis 从 2.8 版本开始提供了 SCAN 系列操作(包括 HSCAN,SSCAN 和 ZSCAN),这类操作实现了渐进式遍历,每次只返回有限数量的数据。这样一来,相比于 HGETALL、SMEMBERS 这类操作来说,就避免了一次性返回所有元素而导致的 Redis 阻塞。
第三,统计操作,是指集合类型对集合中所有元素个数的记录,例如 LLEN 和 SCARD。这类操作复杂度只有 O(1),这是因为当集合类型采用压缩列表、双向链表、整数数组这些数据结构时,这些结构中专门记录了元素的个数统计,因此可以高效地完成相关操作。
第四,例外情况,是指某些数据结构的特殊记录,例如压缩列表和双向链表都会记录表头和表尾的偏移量。这样一来,对于 List 类型的 LPOP、RPOP、LPUSH、RPUSH 这四个操作来说,它们是在列表的头尾增删元素,这就可以通过偏移量直接定位,所以它们的复杂度也只有 O(1),可以实现快速操作。

posted @ 2020-11-11 10:44  SH金刚狼  阅读(1848)  评论(0编辑  收藏  举报