深入剖析Redis系列 – Redis数据结构与全局命令概述
前言
Redis?提供了?5?种数据结构。了解每种数据结构的特点,对于?Redis?的?开发运维?非常重要,同时掌握?Redis?的?单线程命令解决?机制,会使?数据结构?和?命令?的选择事半功倍。
接下来的几篇文章,将从如下几个方面详情?Redis?的几种数据结构,命令使用及其应用场景。
预备知识:几个简单的?全局命令,数据结构?和?内部编码,单线程命令?解决机制分析。
数据结构特性:5?种?数据结构?的特点、命令使用、应用场景。
数据管理:键管理、遍历键、数据库管理。
正文
1. 预备知识
在详情?5?种?数据结构?之前,需要先理解?Redis?的少量?全局命令、数据结构?和?内部编码、单线程命令解决机制。
Redis?的命令有?上百个,了解?Redis?的少量机制,会发现这些命令有很强的?通用性。
Redis?不是万金油,有些?数据结构?和?命令?必需在?特定场景?下使用,一旦?使用不当?可能对?Redis?本身?或者者?应用本身?造成致命伤害。
2. 全局命令
Redis?有?5?种?数据结构,它们是?键值对?中的?值,对于?键?来说有少量通用的命令。
2.1. 查看所有键
keys *
下面插入了?3?对字符串类型的键值对:
127.0.0.1:6379>?set?hello?world?OK?127.0.0.1:6379>?set?java?jedis?OK?127.0.0.1:6379>?set?python?redis-py?OK?复制代码
命令会将所有的键输出:
127.0.0.1:6379>?keys?*?1)?”python”?2)?”java”?3)?”hello”?复制代码
2.2. 键总数
dbsize
下面插入一个?列表类型?的?键值对(值是?多个元素?组成):
127.0.0.1:6379>?rpush?mylist?a?b?c?d?e?f?g?(integer)?7?复制代码
dbsize?命令会返回当前数据库中?键的总数。
127.0.0.1:6379>?dbsize?(integer)?4?复制代码
dbsize?命令在?计算键总数?时?不会遍历?所有键,而是直接获取?Redis?内置的键总数变量,所以?dbsize?命令的?时间复杂度?是?O(1)。而?keys?命令会?遍历?所有键,所以它的?时间复杂度?是?O(n),当?Redis?保存了?大量键?时,线上环境?禁止?使用。
2.3. 检查键能否存在
exists key
假如键存在则返回?1,不存在则返回?0:
127.0.0.1:6379>?exists?java?(integer)?1?127.0.0.1:6379>?exists?not_exist_key?(integer)?0?复制代码
2.4. 删除键
del key
del?是一个?通用命令,无论值是什么?数据结构?类型,del?命令都可以将其?删除。
127.0.0.1:6379>?del?java?(integer)?1?127.0.0.1:6379>?exists?java?(integer)?0?127.0.0.1:6379>?del?not_exist_key?(integer)?0?127.0.0.1:6379>?exists?not_exist_key?(integer)?0?复制代码
返回结果为?成功删除?的?键的个数,假设删除一个?不存在?的键,就会返回?0。
2.5. 键过期
expire key seconds
Redis?支持对?键?增加?过期时间,当超过过期时间后,会?自动删除键,例如为键?hello?设置?10?秒过期时间:
127.0.0.1:6379>?set?hello?world?OK?127.0.0.1:6379>?expire?hello?10??(integer)?0?复制代码
ttl?命令会返回键的?剩余过期时间,它有?3?种返回值:
大于等于?0?的整数:表示键?剩余?的?过期时间。
返回?-1:键?没设置?过期时间。
返回?-2:键?不存在。
可以通过?ttl?命令观察?键?hello?的?剩余过期时间:
#?还剩7秒?127.0.0.1:6379>?ttl?hello(integer)??(integer)?7?…?#?还剩1秒?127.0.0.1:6379>?ttl?hello(integer)??(integer)?1?#?返回结果为-2,说明键hello已经被删除?127.0.0.1:6379>?ttl?hello(integer)??(integer)?-2?127.0.0.1:6379>?get?hello?(nil)?复制代码
2.6. 键的数据结构类型
type key
例如键?hello?是的值?字符串类型,返回结果为?string。键?mylist?的值是?列表类型,返回结果为?list。假如键不存在,则返回?none。
127.0.0.1:6379>?set?a?b?OK?127.0.0.1:6379>?type?a?string?127.0.0.1:6379>?rpush?mylist?a?b?c?d?e?f?g?(integer)?7?127.0.0.1:6379>?type?mylist?list?复制代码
3. 数据结构和内部编码
type?命令实际返回的就是当前?键?的?数据结构类型,它们分别是:string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合),但这些只是?Redis?对外的?数据结构。如图所示:
对于每种?数据结构,实际上都有自己底层的?内部编码?实现,而且是?多种实现。这样?Redis?会在合适的?场景?选择合适的?内部编码,如图所示:
可以看到,每种?数据结构?都有?两种以上?的?内部编码实现。例如?list?数据结构?包含了?linkedlist?和?ziplist?两种?内部编码。同时有些?内部编码,例如?ziplist,可以作为?多种外部数据结构?的内部实现,可以通过?object encoding?命令查询?内部编码:
127.0.0.1:6379>?object?encoding?hello?”embstr”?127.0.0.1:6379>?object?encoding?mylist?”quicklist”?复制代码
可以看到键?hello?对应值的?内部编码?是?embstr,键?mylist?对应值的?内部编码?是?ziplist。
Redis?这样设计有两个好处:
其一:可以改进?内部编码,而对外的?数据结构?和?命令?没有影响。例如?Redis3.2?提供的?quicklist,结合了?ziplist?和?linkedlist?两者的优势,为?列表类型?提供了一种?更加高效?的?内部编码实现。
其二:不同?内部编码?可以在?不同场景?下发挥各自的?优势。例如?ziplist?比较?节省内存,但是在列表?元素比较多?的情况下,性能?会有所?下降,这时候?Redis?会根据?配置,将列表类型的?内部实现?转换为?linkedlist。
4. 单线程架构
Redis?使用了?单线程架构?和?I/O?多路复用模型?来实现?高性能?的?内存数据库服务。那为什么?单线程?还能这么快,下面分析起因:
4.1. 纯内存访问
Redis?将所有数据放在?内存?中,内存的?响应时长?大约为?100?纳秒,这是?Redis?达到?每秒万级别?访问的重要基础。
4.2. 非阻塞I/O
Redis?使用?epoll?作为?I/O?多路复用技术?的实现,再加上?Redis?自身的?事件解决模型?将?epoll?中的?连接、读写、关闭?都转换为?事件,从而不用不在?网络?I/O?上白费过多的时间,如图所示:
4.3. 单线程避免线程切换和竞态产生的消耗
采用?单线程?就能达到如此?高的性能,那么不失为一种不错的选择,由于?单线程?能带来几个好处:
单线程?可以简化?数据结构和算法?的实现,开发人员不需要理解复杂的?并发数据结构。
单线程?避免了?线程切换?和?竞态?产生的消耗,对于服务端开发来说,锁和线程切换?通常是性能杀手。
单线程?的问题:对于?每个命令?的?执行时间?是有要求的。假如某个命令?执行过长,会造成其余命令的?阻塞,对于?Redis?这种?高性能?的服务来说是致命的,所以?Redis?是面向?快速执行?场景的数据库。
小结
本文堆?Redis?的几种?数据结构?进行了概述,详情了几个简单的?全局命令,数据结构?和?内部编码?以及?单线程命令?解决机制分析。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 深入剖析Redis系列 – Redis数据结构与全局命令概述