多语网站wordpress子站点,高端公司小程序建设,网页美工制作网站,python 开发手机网站开发通用命令
get() / set()
这是Redis中两个最为核心的命令。
set插入 这里的key 和 value都是字符串#xff0c;我们可以加双引号 或者单引号#xff0c;或者不加。
get查找 如果查询的key值不存在#xff0c;那么会返回一个 nil #xff0c;也就是代表空 在Redis中命令…通用命令
get() / set()
这是Redis中两个最为核心的命令。
set插入 这里的key 和 value都是字符串我们可以加双引号 或者单引号或者不加。
get查找 如果查询的key值不存在那么会返回一个 nil 也就是代表空 在Redis中命令是不区分大小写的。 这就是Redis最核心的命令和它俩的使用方法了看起来就像是一个网络版的hash map一样。这也是Redis的一个优势使用简单 学习成本低。
keys()
在这里补充一下 Redis全局命令的概念 Redis支持很多的数据结构从整体上来说Redis是键值对结构key是固定的字符串但是value实际上会有多种类型比如
字符串 哈希表 列表 集合 有序集合一般来说操作不同的数据结构就会有不同的命令。
而全局命令就是能够搭配任意一个数据结构使用的命令。
keys()用来查询当前服务器上匹配的key。
语法
KEYS pattern
其中 pattern模式是包含特殊符号的字符串。
这个pattern存在的意义是为了描述另外的字符串长什么样
pattern的使用规则 一般生产环境中是禁止使用keys的尤其是 keys *。 注意keys 命令的时间复杂度 ON的又因为redis是单线程的所以当数据量很大时用 keys * 就把redis阻塞了无法给其他客户端提供服务。
这样带来的结果往往是灾难性的因为redis作为缓存它是挡在mysql前帮mysql分担请求的如果此时redis阻塞了那么请求突然就全打往mysql了mysql可能会突然承受不主压力而挂掉了如果mysql也挂了那整个服务差不多也瘫痪了。 exists()
exists()判断key是否存在。 这里的key可以是多个。
返回值 有效key的个数
针对多个key来说这是挺有用的。 Redis组织这些key就是按照哈希表的方式来组织的。
关于这个命令的时间复杂度 官方给出的是 ON但是注意这里的ON中的N指的是我们传入的key的个数不是传统意义上的ON。
有两种写法 如上第一种写法查询一次第二种解法查询两次那么这两种写法有什么区别呢
我们始终要记住Redis是 客户端 - 服务器结构的程序而客户端 与 服务器之间是通过网络来通信的因此分开的写法会产生更多的轮次的网络通信导致效率变低。 del()
删除指定的key
可以一次删除一个或者多个
时间复杂度 N跟exists一样
返回值删掉的key的个数 而Redis删除数据的严重性要看应用场景 不过归根结底还是不要乱删数据。 expire()
给指定的key设置过期时间 语法
EXPIRE key seconds 成功时返回1失败时返回0
其中seconds的单位是秒。
这个key得是之前就有的不然这个命令就会执行失败。
时间复杂度 O1
这个命令在有时间限制的场景下应用很广泛比如手机验证码有效时间。
另外还有关于基于redis实现的分布式锁 补充
一秒对于计算机来说还是很漫长的所以还有一个命令 pexpire 也就是多加了个p此时seconds的单位就是毫秒了用法跟 expire是一样的。 ttl()
查看指定的key的过期时间。单位秒级
这里的ttl跟网络IP协议那里的TTL是不一样的。 返回值
返回剩余的过期时间。如果该key没有关联过期时间返回-1如果该key不存在返回-2。 同样还有一个命令 pttl 。用法一样不过单位是毫秒。 补充 Redis的key过期策略
Redis的过期策略是怎么实现的呢 这也是一道经典的面试题。
如果直接遍历所有key的方式来检查哪些key过期了效率未免太低了。 对此Redis整体的策略有
1.定期删除
周期性的每次抽取一部分key进行验证过期时间。 Redis会保证这个抽查的速度足够快。
为什么对于定期删除有明确的速度要求只抽取一部分验证来保证抽查速度快呢
因为Redis是单线程的程序它的主要任务都是在单线程中执行的如果扫描过期的key消耗的时间太多了就有可能导致正常处理请求命令被阻塞了产生了类似执行 key * 的效果。
2.惰性删除
假设这个key已经过期了但是暂时还没有删除它当紧接着后面的一次访问正好用到了这个key那么服务器就触发了删除key的操作同时再返回一个nil。
在Redis中这两种删除策略是搭配在一起使用的但是仍然会存在很多过期的key残留在服务器上没有及时删除掉为此Redis还提供了一系列内存淘汰策略。
扩展 理解定时器的实现原理
1.基于优先级队列/堆
正常的队列是先进先出而优先级队列是按照指定的优先级优先级高的先出。
这个优先级是可以自定义的。
在Redis过期key销毁的场景中距离过期时间越近那么优先级就越高。
我们把设置了过期时间的key放入到这个堆中那么堆顶元素就是最早会过期的key。
此时定时器只要分配一个线程去检查这个堆顶查看堆顶的元素是否过期即可。
也就是不需要遍历所有key而是只需要检查堆顶元素即可。
另外检查堆顶元素的周期也不能太短 对于下一次检查的时间可以设置为堆顶元素距离过期的时间。在此期间就让这个线程阻塞挂起就可以了。
另外如果新来了一个元素那么也会唤醒这个线程会重新设置下一次的检查时间。
2.基于时间轮实现的定时器 如图就是一个循环数组把时间划分成很多小段划分的粒度要看实际需求。
时间轮运行的时候有一个指针这个指针每次会按照固定的时间间隔向前移动这个时间间隔就是我们划分的时间粒度每走到一个格子上就会尝试执行这个格子上链表的所有任务为什么是尝试呢假设某个key的过期时间超过了这个时间轮能表示的最大时间那么就会让这个key多转几圈然后放到对应格子的链表上。并且在执行销毁任务时还是会检查一下过期时间的如果发现还没有到就不会销毁的。 type()
返回这个key对应的value的数据类型。
注意Redis中key的类型只有string。
返回类型 返回值为none就是没有这个key。
使用示例 对于操作链表插入的命令是 lpush 后面跟元素值对于集合 插入命令是sadd对于哈希表插入命令是hset可见命令都是不一样的。 常用数据结构
redis常用的数据结构有 字符串哈希列表集合有序集合。 另外Redis在底层实现这些数据结构的时候会在源码层面针对上面的数据结构的实现进行特定的优化来达到节省时间/空间的效果也就是内部具体的数据结构编码方式还会有变数。 总结同一个数据类型背后的编码实现方式可能是不同的会根据特定的场景进行优化 比如string类型当value就是一个整数的时候此时Redis可能直接会使用int来保存。
再比如hash表当数据元素比较少时会用一个ziplist来存储以此来压缩空间因为当元素比较少时它遍历的速度也很快。 关于为什么要压缩 再看看list set zset 并且在有序集合那里底层的实现有跳表因为有序集合里的元素是带有权值的当需要在某个权值范围内遍历的时候用跳表就比较合适。 并且在list和zset的ziplist那里从Redis3.2开始就引入了新的实现方式quicklist。 可以使用命令
object encoding key
来查询这个key底层的编码方式 关于Redis单线程模型
Redis单线程工作过程
Redis只用一个线程来处理所有的命令请求。但是不是说Redis服务器内部真的只有一个线程其他的多线程都是在网络部分处理IO的。
因为Redis实际处理请求是单线程所以它保证了对收到来自不同客户端的请求的处理是串行化的也就是不会有线程安全问题。
关于Redis能够使用单线程模型的主要原因Redis的核心业务逻辑都是 短平快 的这样的话就不吃CPU资源也就不吃多核了所以Redis使用单线程也能很好的工作。
弊端就是Redis必须特别小心某个操作的时间过长这样会阻塞其他命令的执行。 Redis单线程快在哪里
Redis虽然是单线程但是为什么效率高速度快经典面试题
首先 Redis的效率高速度快 是参照于 数据库MySQL OracleSQL Server的。
原因 1.Redis访问的是内存而MySQL这样的数据库访问的是硬盘。
2.Redis的核心逻辑比那些数据库的核心功能要简单。 3.单线程模型避免了一些不必要的线程竞争开销。
因为Redis的基本操作都是 短平快的也就是简单操作一下内存不是什么特别消耗CPU的操作就算是多线程也提升不大。
4.处理网络IO的时候用了epoll这样的多路复用机制。 IO多路复用适合交互不是很频繁大部分时间都在等的场景如果交互十分频繁比如下载文件或者直播此时还是创建一个线程来处理比较好。