成品软件网站推荐,网站图标文件下载,网站策划建设,网上可以注册公司吗?都需要什么目录 引言
Redis 全局命令
SET GET
KEYS
EXISTS
DEL
EXPIRE
TTL
TYPE
redis 引入定时器高效处理过期 key
基于优先级队列方式
基于时间轮方式 引言 Redis 是根据键值对的方式存储数据的必须要进入 redis-cli 客户端程序 才能输入 redis 命令 Redis 全局命令 R…目录 引言
Redis 全局命令
SET GET
KEYS
EXISTS
DEL
EXPIRE
TTL
TYPE
redis 引入定时器高效处理过期 key
基于优先级队列方式
基于时间轮方式 引言 Redis 是根据键值对的方式存储数据的必须要进入 redis-cli 客户端程序 才能输入 redis 命令 Redis 全局命令 Redis 支持很多种数据结构整体上来说Redis 是键值对结构key 固定为字符串类型但 value 有很多种类型如 字符串、哈希表、列表、集合、有序集合 等操作不同的数据结构就会有不同的命令全局命令就是能够搭配任意一个数据结构来使用的命令 SET GET set 根据 key 和 value 来存数据key 和 value 都是字符串类型 语法 set key value 实例理解 对于上述的 key value 不加上引号其表示的就是字符串类型当然也可以给 key 和 value 加上引号单引号 或 双引号 都行 注意 redis 中的命名不区分大小写 get 根据 key 来取 valueget 命令直接输入 key 就能得到 value 语法 get key 实例理解 如果当前 key 不存在就会直接返回 nil 此处的 nil 和 null、NULL 表示同一个意思 KEYS 用来查询当前服务器上能匹配的 key通过一些特殊符号通配符来描述 key 的模样能匹配上述模样的 key 就能被查询出来 时间复杂度 O(N) 语法 keys pattern 此处的 pattern 为包含特殊符号的字符串其存在的意义是去描述 另外的字符串长啥样的 匹配任意一个字符*匹配 0 个或者多个任意字符[ab]只能匹配到 a b 别的都不行 相当于给出固定的选项[^ae]只有 a、e 匹配不了 其他的都能匹配[a-e]匹配 a - e 这个范围内的字符 包含两侧边界 实例理解 此处我们随意添加几个 键值对 通配符 * 通配符 [ab] 通配符 [^ae] 通配符 [a-e] 通配符 注意 上述匹配规则不需要刻意去背 注意事项 keys 命令的时间复杂度是 O(N)所以 在生产环境上 一般会禁止使用 keys 命令尤其是 keys * 即查询 redis 中所有的 key 原因 生产环境上的 key 可能会非常多redis 是一个单线程的服务器如果执行 keys * 的时间过长可能导致 redis 服务器被阻塞从而无法给其他客户端提供服务 严重后果 redis 经常被用作缓存 挡在 mysql 前面如果 redis 被 keys * 阻塞了那么此时其他查询 redis 的操作便会超时从而这些请求就会 直接查询 mysql 数据库这么一大波 突然来临的请求会让 mysql 措手不及进而导致 mysql 数据库挂掉最终导致整个系统瘫痪 EXISTS 判定 key 是否存在 时间复杂度 O(1)redis 按照 哈希表 的方式组织这些 key 语法 exists key [key...] 返回值 我们的 exists 是可以判断多个 key 是否存在的所以其返回值为 key 存在的个数 实例理解 注意事项 此处红框写法 与 绿框写法 相差很大 原因 redis 是一个 客户端 服务器 结构的程序客户端和服务器之间通过 网络 来进行通信绿框写法 相较于 红框写法 会产生更多轮次的网络通信 补充 网络通信 相较于 直接操作内存效率更低、成本更高所以 redis 很多命令均支持一次能操作多个 key 或者 支持多种操作 DEL 删除指定的 key可以一次删除 一个 或 多个 时间复杂度 O(1) 语法 del key [key ...] 返回值 删除掉的 key 的个数 实例理解 注意事项 学 mysql 的时候像删除 类型的操作如 drop database、drop table 等 都是非常危险的操作一旦删除数据就无了redis 主要的应用场景为 用作缓存此时 redis 中存的只是 热点数据全量数据均存在 mysql 数据库中如果把 redis 中的 key 删除几个一般来说问题不会大但是如果把 所有的数据 或 一大半的数据 都删除这种影响便会很大 原因 本来 redis 是帮 mysql 负重前行的此时 redis 中没数据了mysql 便需要应对大量的请求然后 mysql 便会很容易挂掉 补充 相比之下如果是 mysql 数据库哪怕误删了一个数据 都可能会造成很大的影响但是如果把 redis 也作为数据库此时误删数据也会造成很大的影响因为此时 redis 中存储的是 全量数据如果把 redis 作为消息队列这种情况误删数据影响大不大需要具体问题具体分析 总结 不要乱删数据 EXPIRE 给指定的 key 设置过期时间即 key 存活时间超出这个指定的值就会被自动删除 语法 此处的时间单位为 秒 expire key seconds 对于计算机来说秒是一个非常长的时间此处的时间单位为 毫秒 pexpire key millisecond 返回值 此处设定过期时间 必须是针对已经存在的 key 设置设置成功返回 1 设置失败 返回 0 实例理解 经典业务场景 很多业务场景是有时间限制的比如手机验证码点外卖的优惠券在指定时间内有效、基于 redis 实现分布式锁 redis 实现分布式锁 为了不能避免出现不能正确解锁的情况通常都会在加锁的时候设置一下过期时间所谓的 redis 作为分布式锁就是给 redis 里写一个特殊的 key value TTL 查看当前 key 的过期时间时间单位为 秒 时间复杂度 O(1) 语法 ttl key 返回值 剩余过期时间 -1 表示没有关联过期时间 -2 表示 key 不存在 实例理解 redis 相关的经典面试题 redis 中 key 的过期策略是怎么实现的 理解 一个 redis 中可能同时存在很多 key这些 key 中可能有很大一部分都有过期时间此时 redis 服务器咋知道哪些 key 已经过期要被删除哪些 key还没过期 回答 redis 的整体策略有三种 1、定期删除 此处需要结合定期删除的操作即每次抽取一部分验证过期时间必须保证这个抽取检查的过程足够快为啥这里对于定期删除的时间 有明确的要求呢因为 redis 是单线程的程序其主要的任务为 处理每个命令的任务如果扫描过期的 key 消耗时间太多就可能导致正常处理请求命令被阻塞即产生了类似于 keys * 这样的效果 2、惰性删除 假设一个 key 已经到过期时间了此时并不会将其直接删除即 key 还会保存在 redis 中紧接着如果后面的访问中用到了这个 key 那么此次访问将会让 redis 服务器触发删除 key 的操作与此同时再返回一个 nil 3、内存淘汰策略 注意 redis 中没有采取 定时器 的方式实现过期 key 的删除如果有多个 key 过期 也可以通过一个定时器在高效 且 节省 cpu 的前提下 来处理多个 key如 基于优先级队列 或 基于时间轮 均可以实现比较高效的定时器 TYPE 返回 key 对应 value 的数据类型 时间复杂度 O(1) 语法 type key 返回值 none、string、list、set、zset、hash、stream 等none 表示 key 不存在stream 表示当 redis 作为消息队列的时候value 将使用这个类型 实例理解 注意 在 redis 中上述类型操作方式差别很大使用的命令都是完全不同的 redis 引入定时器高效处理过期 key redis 引入定时器实现高效处理过期 key 有两种方式 基于优先级队列方式 当然也可以通过 堆 的方式 基本概念 正常队列为先进先出优先级队列则是 按照自定义指定的优先级 先出在 redis 处理过期 key 场景中可以设置优先级为过期时间越早 优先级越高 实例理解 假设有很多 key 被设置了过期时间 此时定时器中只要分配一个线程让这个线程去检查队首元素 看其是否过期即可如果队首元素还没过期在队首元素之后元素一定没过期 优势 此时 扫描线程 无需遍历所有 key 仅需盯住 队首元素 即可 补充 在 扫描线程 检查队首元素过期时间时根据 过期时间 与 当前时间 之差来设置一个等待时间当等待时间差不多到了系统再唤醒该线程此时扫描线程便不需要高频扫描 队首元素把 cpu 的开销也节省下来了 问题 在线程休眠的时候 插入了一个新 key且该 key 的过期时间为 1030 解决办法 在新任务添加的时候唤醒一下正在休眠的线程即重新检查一下 队首元素再根据时间差距重新调整阻塞时间 基于时间轮方式 把时间划分成多个小段对于时间轮来说每个格子是多少时间一共多少个格子都是需要根据实际场景灵活调配的