[{"data":1,"prerenderedAt":58},["ShallowReactive",2],{"article-97":3},{"code":4,"msg":5,"data":6,"count":14},200,"查询成功",{"id":7,"title":8,"keywords":9,"description":10,"category_id":11,"content":12,"body_html":13,"thumb_up":14,"clicks":15,"sort":14,"remark":16,"status":17,"is_open":17,"is_deleted":14,"is_top":14,"is_recommend":17,"create_time":18,"update_time":19,"image_id":20,"url":13,"member_id":14,"cate_name":21,"prev":22,"next":25,"tags":28,"words":34,"read_time":35,"comments":14,"cover":36,"relevant":37},97,"Redis必知必会的知识点","Redis,数据库,非关系数据库","Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库，并提供多种语言的 API。Redis 通常被称为数据结构服务器，因为值（value）可以是字符串(String)、哈希(Hash)、列表(list)、集合(sets)和有序集合(sorted sets)等类型。",13,"###### 一、单线程的Redis为什么快\n\n纯内存操作、单线程操作，避免了频繁的上下文切换、合理高效的数据结构、采用了非阻塞I\u002FO多路复用机制\n\n###### 二、Redis的数据结构及使用场景\n\n1、String字符串：字符串类型是Redis最基础的数据结构，首先键都是字符串类型，而且其他几种数据结构都是在字符串类型基础上构建的，我们常使用的`set key value` 命令就是字符串。常用在缓存、计数、共享Session、限速等。\n\n2、Hash哈希：在Redis中，哈希类型是指键值本身又是一个键值对结构，哈希可以用来存放用户信息，比如实现购物车。\n\n3、List列表（双向链表）：列表类型是用来存储多个有序的字符串。可以做简单的消息队列的功能。\n\n4、Set集合：集合类型也是用来保存多个的字符串元素，但和列表类型不一 样的是，集合中不允许有重复元素，并且集合中的元素是无序的，不能通过索引下标获取元素。利用Set的交集、并集、差集等操作，可以计算共同喜好，全部的喜好，自己独有的喜好等功能。\n\n5、Sorted Set有序集合（跳表实现）：Sorted Set多了一个权重参数Score，集合中的元素能够按 Score进行排列。可以做排行榜应用，取`TOP N`操作。\n\n###### 三、Redis的数据过期策略\n\nRedis中数据过期策略采用 `定期删除+惰性删除` 策略\n\n1、定期删除策略：Redis 启用一个定时器定时监视所有的 `key`，判断`key`是否过期，过期的话就删除。这种策略可以保证过期的 `key`  最终都会被删除，但是也存在严重的缺点：每次都遍历内存中所有的数据，非常消耗 CPU 资源，并且当 `key`  已过期，但是定时器还处于未唤起状态，这段时间内 `key` 仍然可以用。\n\n2、惰性删除策略：在获取 `key` 时，先判断 `key` 是否过期，如果过期则删除。这种方式存在一个缺点：如果这个 `key` 一直未被使用，那么它一直在内存中，其实它已经过期了，会浪费大量的空间。\n\n3、这两种策略天然的互补，结合起来之后，定时删除策略就发生了一些改变，不再是每次扫描全部的 `key` 了，而是随机抽取一部分 `key` 进行检查，这样就降低了对 CPU  资源的损耗，惰性删除策略互补了未检查到的`key`，基本上满足了所有要求。但是有时候就是那么的巧，既没有被定时器抽取到，又没有被使用，这些数据又如何从内存中消失？没关系，还有内存淘汰机制，当内存不够用时，内存淘汰机制就会上场。\n\n淘汰策略分为：\n\n当内存不足以容纳新写入数据时，新写入操作会报错。\n\n（Redis 默认策略）当内存不足以容纳新写入数据时，在键空间中，移除最近最少使用的  `Key`。\n\n（LRU推荐使用）当内存不足以容纳新写入数据时，在键空间中，随机移除某个  `Key`。\n\n当内存不足以容纳新写入数据时，在设置了过期时间的键空间中，移除最近最少使用的 `Key`。\n\n这种情况一般是把 `Redis`  既当缓存，又做持久化存储的时候才用。\n\n当内存不足以容纳新写入数据时，在设置了过期时间的键空间中，随机移除某个  `Key`。\n\n当内存不足以容纳新写入数据时，在设置了过期时间的键空间中，有更早过期时间的 `Key` 优先移除。\n\n###### 四、Redis的set和setnx\n\nRedis中`setnx`不支持设置过期时间，做分布式锁时要想避免某一客户端中断导致死锁，需设置`lock`过期时间，在高并发时 `setnx`与 `expire` 不能实现原子操作，如果要用，得在程序代码上显示的加锁。\n\n使用`SET`代替`SETNX`  ，相当于`SETNX+EXPIRE`实现了原子性，不必担心`SETNX`成功，`EXPIRE`失败的问题。\n\n###### 五、Redis的LRU具体实现：\n\n传统的`LRU`是使用栈的形式，每次都将最新使用的移入栈顶，但是用栈的形式会导致执行`select  *`的时候大量非热点数据占领头部数据，所以需要改进。\n\nRedis每次按`key`获取一个值的时候，都会更新`value`中的`lru`字段为当前秒级别的时间戳。\n\nRedis初始的实现算法很简单，随机从`dict`中取出五个`key`，淘汰一个`lru`字段值最小的。\n\n在3.0的时候，又改进了一版算法，首先第一次随机选取的`key`都会放入一个`pool`中(pool的大小为16)，`pool`中的`key`是按`lru`大小顺序排列的。\n\n接下来每次随机选取的`key lru`值必须小于`pool`中最小的`lru`才会继续放入，直到将`pool`放满。放满之后，每次如果有新的`key`需要放入，需要将`pool`中`lru`最大的一个`key`取出。淘汰的时候，直接从`pool`中选取一个`lru`最小的值然后将其淘汰。\n\n###### 六、Redis如何发现热点key\n\n1、凭借经验，进行预估：例如提前知道了某个活动的开启，那么就将此`Key`作为热点`Key`。\n\n2、服务端收集：在操作`redis`之前，加入一行代码进行数据统计。\n\n3、抓包进行评估：`Redis`使用TCP协议与客户端进行通信，通信协议采用的是`RESP`，所以自己写程序监听端口也能进行拦截包进行解析。\n\n4、在`proxy`层，对每一个 `redis` 请求进行收集上报。\n\n5、Redis自带命令查询：Redis4.0.4版本提供了`redis-cli  –hotkeys`就能找出热点`Key`。（如果要用`Redis`自带命令查询时，要注意需要先把内存逐出策略设置为`allkeys-lfu`或者`volatile-lfu`，否则会返回错误。进入Redis中使用`config set maxmemory-policy allkeys-lfu`即可。）\n\n###### 七、Redis的热点key解决方案\n\n1、服务端缓存：即将热点数据缓存至服务端的内存中。(利用`Redis`自带的消息通知机制来保证`Redis`和服务端热点`Key`的数据一致性，对于热点`Key`客户端建立一个监听，当热点`Key`有更新操作的时候，服务端也随之更新。)\n\n2、备份热点Key：即将热点`Key+`随机数，随机分配至`Redis`其他节点中。这样访问热点`key`的时候就不会全部命中到一台机器上了。\n\n###### 八、如何解决 Redis 缓存雪崩问题\n\n1、使用 Redis 高可用架构：使用 `Redis` 集群来保证 `Redis` 服务不会挂掉。\n\n2、缓存时间不一致，给缓存的失效时间，加上一个随机值，避免集体失效。\n\n3、限流降级策略：有一定的备案，比如个性推荐服务不可用了，换成热点数据推荐服务。\n\n###### 九、如何解决 Redis 缓存穿透问题\n\n1、在接口做校验。\n\n2、存`null`值（缓存击穿加锁,或设置不过期）\n\n3、布隆过滤器拦截：将所有可能的查询 `key`  先映射到布隆过滤器中，查询时先判断`key`是否存在布隆过滤器中，存在才继续向下执行，如果不存在，则直接返回。布隆过滤器将值进行多次哈希`bit`存储，布隆过滤器说某个元素在，可能会被误判。布隆过滤器说某个元素不在，那么一定不在。\n\n###### 十、Redis的持久化机制\n\nRedis为了保证效率，数据缓存在了内存中，但是会周期性地把更新的数据写入磁盘或者把修改操作写入追加的记录文件中，以保证数据的持久化。`Redis`的持久化策略有两种：\n\n1、RDB：快照形式是直接把内存中的数据保存到一个 `dump` 的文件中，定时保存，保存策略。当`Redis` 需要做持久化时，`Redis` 会 `fork` 一个子进程，子进程将数据写到磁盘上一个临时RDB文件中。当子进程完成写临时文件后，将原来的RDB替换掉。\n\n2、AOF：把所有的对 `Redis` 的服务器进行修改的命令都存到一个文件里，命令的集合。\n\n使用 `AOF` 做持久化，每一个写命令都通过 `write` 函数追加到 `appendonly.aof` 中。`aof` 的默认策略是每秒钟 `fsync` 一次，在这种配置下，就算发生故障停机，也最多丢失一秒钟的数据。缺点是对于相同的数据集来说，AOF的文件体积通常要大于RDB文件的体积。根据所使用的 `fsync`策略，AOF的速度可能会慢于RDB。Redis默认是快照RDB的持久化方式。对于主从同步来说，主从刚刚连接的时候，进行全量同步（RDB）；全同步结束后，进行增量同步(AOF)。\n\n###### 十一、Redis的事务\n\n1、Redis  事务的本质是一组命令的集合。事务支持一次执行多个命令，一个事务中所有命令都会被序列化。在事务执行过程，会按照顺序串行化执行队列中的命令，其他客户端提交的命令请求不会插入到事务执行命令序列中。总结说：`redis` 事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。\n\n2、Redis事务没有隔离级别的概念，批量操作在发送 `EXEC` 命令前被放入队列缓存，并不会被实际执行，也就不存在事务内的查询要看到事务里的更新，事务外查询不能看到。\n\n3、Redis中，单条命令是原子性执行的，但事务不保证原子性，且没有回滚。事务中任意命令执行失败，其余的命令仍会被执行。\n\n###### 十二、Redis事务相关命令\n\n1、watch key1 key2 ... : 监视一或多个 `key`,如果在事务执行之前，被监视的 `key` 被其他命令改动，则事务被打断（类似乐观锁）\n\n2、multi : 标记一个事务块的开始（queued）\n\n3、exec : 执行所有事务块的命令（一旦执行exec后，之前加的监控锁都会被取消掉）\n\n4、discard : 取消事务，放弃事务块中的所有命令\n\n5、unwatch : 取消 `watch` 对所有 `key` 的监控\n\n###### 十三、Redis和 memcached 的区别\n\n1、存储方式上：`memcache` 会把数据全部存在内存之中，断电后会挂掉，数据不能超过内存大小。`redis`有部分数据存在硬盘上，这样能保证数据的持久性。\n\n2、数据支持类型上：`memcache` 对数据类型的支持简单，只支持简单的`key-value`，而 `redis` 支持五种数据类型。\n\n3、用底层模型不同：它们之间底层实现方式以及与客户端之间通信的应用协议不一样。`redis` 直接自己构建了VM机制，因为一般的系统调用系统函数的话，会浪费一定的时间去移动和请求。\n\n4、value的大小：`redis` 可以达到1GB，而 `memcache` 只有1MB\n\n###### 十四、Redis的几种集群模式\n\n主从复制、哨兵模式、cluster模式\n\n###### 十五、Redis的哨兵模式\n\n哨兵是一个分布式系统,在主从复制的基础上你可以在一个架构中运行多个哨兵进程,这些进程使用流言协议来接收关于 `Master` 是否下线的信息，并使用投票协议来决定是否执行自动故障迁移，以及选择哪个 `Slave` 作为新的 `Master`。\n\n每个哨兵会向其它哨兵、master、slave定时发送消息,以确认对方是否活着，如果发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓的”主观认为宕机”)。\n\n若“哨兵群“中的多数 `sentinel` ，都报告某一 `master` 没响应，系统才认为该 `master` \"彻底死亡\"(即:客观上的真正down机)，通过一定的 `vote`算法，从剩下的`slave`节点中，选一台提升为`master`，然后自动修改相关配置。\n\n###### 十六、Redis的rehash\n\nRedis的 `rehash` 操作并不是一次性、集中式完成的，而是分多次、渐进式地完成的，`redis` 会维护维持一个索引计数器变量 `rehashidx` 来表示 `rehash` 的进度。\n\n这种渐进式的 `rehash`  避免了集中式 `rehash` 带来的庞大计算量和内存操作，但是需要注意的是`redis` 在进行 `rehash` 的时候，正常的访问请求可能需要做多要访问两次 `hashtable（ht[0]， ht[1]）`，例如键值被 `rehash` 到新 `ht1`，则需要先访问 `ht0` ，如果 `ht0` 中找不到，则去 `ht1`中找。\n\n###### 十七、Redis的hash表被扩展的条件\n\n1、哈希表中保存的key数量超过了哈希表的大小。\n\n2、Redis服务器目前没有在执行 `BGSAVE` 命令（rdb）或 `BGREWRITEAOF` 命令，并且哈希表的负载因子大于等于1。\n\n3、Redis服务器目前在执行 `BGSAVE` 命令（rdb）或 `BGREWRITEAOF` 命令，并且哈希表的负载因子大于等于5。(负载因子 = 哈希表已保存节点数量  \u002F  哈希表大小，当哈希表的负载因子小于0.1时，对哈希表执行收缩操作。)\n\n###### 十八、Redis并发竞争key的解决方案\n\n分布式锁+时间戳、利用消息队列\n\n###### 十九、Redis的管道pipeline\n\n对于单线程阻塞式的 `Redis`，`Pipeline` 可以满足批量的操作，把多个命令连续的发送给`Redis  Server`，然后一一解析响应结果。`Pipelining` 可以提高批量处理性能，提升的原因主要是TCP连接中减少了“交互往返”的时间。`pipeline` 底层是通过把所有的操作封装成流，`redis`有定义自己的出入输出流。在 `sync()` 方法执行操作，每次请求放在队列里面，解析响应包。\n\n###### 二十、Redis与Mysql双写一致性方案\n\n先更新数据库，再删缓存。数据库的读操作的速度远快于写操作的，所以脏数据很难出现。可以对异步延时删除策略，保证读请求完成以后，再进行删除操作。\n\n------------\n**声明**：本文转载于：PHP中文网，如有侵犯，请联系m.yong@foxmail.com删除\n\n",null,0,661,"",1,"2021-04-22 00:21:51","2026-04-19 10:44:56",140,"Redis",{"id":23,"title":24},96,"PHP中字符串跟0做比较永远是true",{"id":26,"title":27},98,"本站点JavaScript相关特效使用方法整理",[29,32],{"id":30,"name":31},28,"数据库",{"id":33,"name":21},76,4651,11,"https:\u002F\u002Ftp.myong.top\u002Fstorage\u002Farticle\u002Fa6\u002Fb893ca219d1ce6b4b96a91423a9b3f.jpg",[38,43,48,53],{"id":39,"title":40,"create_time":41,"description":42},99,"Memcached、MongoDB和Redis的对比区别","2021-04-25 17:37:30","MongoDB 更类似 MySQL，支持字段索引、游标操作，其优势在于查询功能比较强大，擅长查询 JSON 数据，能存储海量数据，但是不支持事务。 Redis 是一个开源（BSD许可）的，内存中的数据结构存储系统，支持多种类型的数据结构，可用作数据库，高速缓存和消息队列代理",{"id":44,"title":45,"create_time":46,"description":47},118,"Redis MONITOR 命令详解：实时监控你的 Redis 服务器","2025-10-10 17:33:27","在 Redis 数据库管理中，实时监控命令执行情况是排查问题、分析性能的重要手段。本文将深入解析 `redis-cli -a rafeily MONITOR` 命令的功能、用法及注意事项，帮助你更好地利用这一强大工具。",{"id":49,"title":50,"create_time":51,"description":52},119,"Workerman中Redis异步连接的实现与优化","2025-10-14 20:45:00","在高并发网络应用中，数据库操作往往成为性能瓶颈。特别是在基于Workerman这类事件驱动的PHP框架中，传统的同步Redis连接会阻塞主进程，导致服务响应延迟增加。异步Redis连接通过非阻塞I\u002FO操作，可以显著提高应用性能，充分利用Workerman的并发处理能力。本文将详细分析在Workerman环境中实现Redis异步连接的多种方案，并比较各自的优缺点。",{"id":54,"title":55,"create_time":56,"description":57},149,"被误解的 Redis 单线程：为什么它依然是快如闪电的秘密","2026-05-25 00:04:13","一提起 Redis 的单线程，总有人觉得这是浪费服务器资源的老古董设计。但当你真正理解它的内存操作本质和 I\u002FO 多线程的演进后，你会发现这是一个把“简单”和“安全”发挥到极致的精妙权衡。这篇文章聊聊 Redis 单线程的那些过人之处，以及它真正怕什么",1783431656177]