value类型
字符串,哈希,列表,集合,有序集合
相对于集合来说,增加了权重
举个例子
该有序集合里面存储的是学生的成绩,该成绩就是权重
Redis在底层实现上述数据结构时,会在源码层面,针对上述实现进行特定优化,来达到节省时间/节省空间的效果,它保证了在应用层展现的是上述类型的特点,但并不保证在底层使用的就是该类型
string类型内部编码
raw:最基本的字符串底层就是一个char数组
int:redis通常也会实现一些计数功能,当value是一个整数的时候,此时redis会直接用int来保存embstr:针对短字符串进行优化
hash内部编码
hashable:最基本的哈希表,redis内部的哈希表的实现,虽然这里的实现方式可能不太一样,但是整体思路和之前学的一致
ziplist:在哈希表里面元素比较少的时候,可能就变成了ziplist(压缩列表),这样可以节省空间,但这样就不会向哈希表那样定值那么快,因为列表需要遍历,所以只适合元素比较少的情况下
为什么在这个位置要选择压缩列表?
因为value可能还是个哈希结构,但是这时的哈希结构并不大,如果采用常用的哈希结构就会出现大量内存浪费的问题,所以引入了这个结构,当哈希不大的时候采取压缩列表,并不会很影响效率,虽然需要遍历压缩列表,但是压缩列表并不大,遍历很快就结束了
list内部编码
linkedlist:正常链表结构
ziplist
从redis3.2开始,引入了新的实现先方式quicklist取代上述两种结构
quick list大概实现方式:
本质还是一个链表,只是链表的每个元素是一个ziplist,把空间和效率都折中的兼顾到,类似于C++中的std::deque
set内部编码
hashable
intset:对特定场景进行优化,该场景为集合中都是整数
zset内部编码
skiplist:跳表,跳表也是链表,不同于普通链表,每个节点上有多个指针域,巧妙的搭配了这些指针域的指向,就可以做到从跳表上查询元素的时间复杂度为O(lo0gN)
ziplist
object encoding
查看key对应的实际编码方式
操作格式
object encoding key
举个例子
object encoding key1redis会根据实际情况,自动选择内部的编码方式
redis单线程模型
redis只使用一个线程,来处理所有请求,不是说redis进程真的只有一个线程,多线程部分用来处理网络IO
问题:两个客户端同时发起请求,相当于“并发”,当两个请求同时请求同一个数据,时候会造成“线程安全”的问题呢?
并不会,因为是单进程执行处理请求,所以当两个请求都来的时候,在redis内部也是要“排队”的,所以他俩并不会同时对一个数据产生影响,所以不会出现“并发”的问题。
为什么这里不选择多线程执行?
redis选择单线程执行任务主要原因就是,redis核心业务都是短平快的,不太消耗CPU资源。也就不吃多核,反而频繁切换线程,加锁解锁,反而是种负担,可能还会影响效率。
redis虽然是单线程模型,为什么效率还这么高?
这里效率高,是相对于关系型数据库来讲的(Mysql,oracl,sql server)
redis访问内存,mysql访问硬盘
redis核心功能比mysql核心功能更加简单
mysql对于核心的插入删除都有复杂的功能支持,这样势必会增大开销,比如针对插入删除,mysql各种约束,都会使mysql做额外的工作
单线程模型,避免了一些不必要的开销
处理网络IO的时候,使用了epoll这样的IO多路复用机制