redis
2021-05-29 14:56:59 2 举报
AI智能生成
Redis是一个开源的,基于内存的数据结构存储系统,可以用作数据库、缓存和消息中间件。它支持多种数据类型,如字符串、列表、集合、散列和有序集合,并提供了丰富的操作命令。Redis具有高性能、高可用性和可扩展性的特点,广泛应用于互联网、企业级应用和云计算领域。通过使用Redis,开发者可以轻松实现数据的高速读写、分布式锁、计数器、排行榜等功能。
作者其他创作
大纲/内容
数据类型
String 字符串
存储结构
SDS 简单动态字符串 可以动态扩容
embstr 和 raw 的区别?
embstr 的使用只分配一次内存空间(因为 RedisObject 和 SDS 是连续的),而 raw 需要分配两次内存空间(分别为 RedisObject 和 SDS 分配空间)。
因此与 raw 相比,embstr 的好处在于创建时少分配一次空间,删除时少释放一次 空间,以及对象的所有数据连在一起,寻找方便。 而 embstr 的坏处也很明显,如果字符串的长度增加需要重新分配内存时,整个 RedisObject 和 SDS 都需要重新分配空间,因此 Redis 中的 embstr 实现为只读。
因此与 raw 相比,embstr 的好处在于创建时少分配一次空间,删除时少释放一次 空间,以及对象的所有数据连在一起,寻找方便。 而 embstr 的坏处也很明显,如果字符串的长度增加需要重新分配内存时,整个 RedisObject 和 SDS 都需要重新分配空间,因此 Redis 中的 embstr 实现为只读。
为什么要对底层的数据结构进行一层包装呢?
通过封装,可以根据对象的类型动态地选择存储结构和可以使用的命令,实现节省 空间和优化查询速度。
子主题
跟String 比较
redis
c
获取字符串长度的复杂度为O(1)
获取字符串长度的复杂度为O(N)
API 是安全的,不会造成缓冲区溢出
API 是不安全的,可能会造成缓冲区溢出
修改字符串长度N次最多执行N次内存重分配
修改字符串长度N次必然需要执行N次内存重分配
可以保存二进制数据和文本文数据
只能保存文本数据
可以使用一部分<string.h>库中的函数
可以使用所有<String.h>库中的函数
命令
set hello word
get hello
get hello
应用场景
热点数据缓存(例如报表,明星出轨),对象缓存,全页缓存。 可以提升热点数据的访问速度。
分布式锁
STRING 类型 setnx 方法,只有不存在时才能添加成功,返回 true。
STRING 类型 setnx 方法,只有不存在时才能添加成功,返回 true。
全局ID
计数器
文章的阅读量,微博点赞数,允许一定的延迟,先写入 Redis 再定时同步到 数据库。
文章的阅读量,微博点赞数,允许一定的延迟,先写入 Redis 再定时同步到 数据库。
限流
INT 类型,INCR 方法 以访问者的 IP 和其他信息作为 key,访问一次增加一次计数,超过次数则返回 false。
INT 类型,INCR 方法 以访问者的 IP 和其他信息作为 key,访问一次增加一次计数,超过次数则返回 false。
存储类型
字符串、整数、浮点数(String)
Hash 哈希
应用场景
存储对象类型的数据 比如对象或者一张表的数据,比 String 节省了更多 key 的空间,也更加便于集中管 理。
StringString 可以做的事情,Hash 都可以做。
购物车
存储类型
多个无序的键值对。添加、获取、移除、单个键值对;获取所有键值对;检查某个键是否存在
存储结构
ziplist
hashtable
命令
子主题
List 列表
存储类型
存储有序的字符串(从左到右),元素可以重复。可以充当队列和栈的角色。 【左推右推左拉右拉】
应用场景
用户消息时间线 timeline 因为 List 是有序的,可以用来做用户时间线
消息队列
List 提供了两个阻塞的弹出操作:BLPOP/BRPOP,可以设置超时时间。
BLPOP:BLPOP key1 timeout 移出并获取列表的第一个元素, 如果列表没有元素 会阻塞列表直到等待超时或发现可弹出元素为止。
BRPOP:BRPOP key1 timeout 移出并获取列表的最后一个元素, 如果列表没有元 素会阻塞列表直到等待超时或发现可弹出元素为止。
队列:先进先出:rpush blpop,左头右尾,右边进入队列,左边出队列。
栈:先进后出:rpush brpop
List 提供了两个阻塞的弹出操作:BLPOP/BRPOP,可以设置超时时间。
BLPOP:BLPOP key1 timeout 移出并获取列表的第一个元素, 如果列表没有元素 会阻塞列表直到等待超时或发现可弹出元素为止。
BRPOP:BRPOP key1 timeout 移出并获取列表的最后一个元素, 如果列表没有元 素会阻塞列表直到等待超时或发现可弹出元素为止。
队列:先进先出:rpush blpop,左头右尾,右边进入队列,左边出队列。
栈:先进后出:rpush brpop
存储结构
quicklist
双向链表
命令
元素增减: lpush queue a
lpush queue b c
rpush queue d e
lpush queue b c
rpush queue d e
Set 集合
存储类型
String 类型的无序集合不允许有重复元素,最大存储数量 2^32-1(40 亿左右)。【添加、获取、移除单个元素,检查一个元素是否存在,计算交、并、差集计算,在集合里面随机获取元素】
操作命令
添加一个或者多个元素 sadd myset a b c d e f g
获取所有元素 smembers myset
统计元素个数 scard myset
随机获取一个元素 srandmember key
随机弹出一个元素 spop myset 移除一个或者多个元素 srem myset d e f
获取所有元素 smembers myset
统计元素个数 scard myset
随机获取一个元素 srandmember key
随机弹出一个元素 spop myset 移除一个或者多个元素 srem myset d e f
应用场景
抽奖 随机获取元素 spop myset
点赞、签到、打卡
存储结构
intset
hashtable
ZSet 有序集合
存储类型
有序,不允许有重复元素
sorted set,有序的 set,每个元素有个 score。 score 相同时,按照 key 的 ASCII 码排序。
【添加、获取、删除元素;根据分值范围或成员获取元素;计算一个键的排名】
sorted set,有序的 set,每个元素有个 score。 score 相同时,按照 key 的 ASCII 码排序。
【添加、获取、删除元素;根据分值范围或成员获取元素;计算一个键的排名】
应用场景
排行榜
存储结构
ziplist
[score,value]键值对数量少于128个;
每个元素的长度小于64字节;
每个元素的长度小于64字节;
skiplist跳表
不满足以上两个条件时使用跳表
总结
lua脚本
内存回收
过期策略
策略方式
立即过期策略
为每个key创建一个定时器(对内存友好,但会占用大量cpu)
惰性过期策略
当访问一个key的时候再判断是否过期(对内存不够友好)
定期过期策略
每过一段扫描一次数据,清除过过期的
redis采用惰性过期策略和定期过期策略
redis通过expire和persist(移除可以的过期时间)设置过期时间和永久生效
算法
LRU 默认 最近最少使用
LFU
Random
持久化
RDB(redis database缩写快照)
在指定的时间间隔内将内存中的数据集快照写入磁盘 fock子进程全量备份文件
RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,存储上非常紧凑。当进行快照持久化时,会开启一个子进程专门负责快照持久化
RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,存储上非常紧凑。当进行快照持久化时,会开启一个子进程专门负责快照持久化
优点
只有一个dump.rdb文件(快照),方便持久化
RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。
性能最大化,子进程完成数据备份,不影响主进程
(生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。)
(生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。)
数据集大时比AOF恢复快
缺点
数据安全性低,在快照持久化期间修改的数据不会被保存,会有数据丢失的问题
fock出的子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。
fock出的子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。
AOF(append only file)
将redis执行的每次命令放到一个日志文件中记录;操作记录保存到文件,增量备份,fock子进程将文件重写 当开启两种方式备份时,优先使用AOF恢复数据
优点
数据安全,可保证数据不丢失
AOF也有三种触发机制
(1)每修改同步always:同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
(2)每秒同步everysec:(默认)异步操作,每秒记录 如果一秒内宕机,有数据丢失 并且就算发生故障停机,也最多只会丢失一秒钟的数据
(3)不同no:从不同步
AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。
(1)每修改同步always:同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
(2)每秒同步everysec:(默认)异步操作,每秒记录 如果一秒内宕机,有数据丢失 并且就算发生故障停机,也最多只会丢失一秒钟的数据
(3)不同no:从不同步
AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。
rewrite模式会对过大的文件进行合并重写,删除其中的某些命令
缺点
AOF文件比RDB文件大,数据恢复启动时慢
redis持久化数据和缓存扩容的方式
缓存扩容方式
使用一致性哈希实现动态扩容缩容
持久化数据扩容方式
必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情
况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。
况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。
选型
如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。
集群
为什么需要集群
水平扩展保证保证高可用 且性能更好
集群方案
主从模式
master
进行读写操作,当读写操作导致数据变化时会自动将数据同步给从数据库
master挂了以后,不会在slave节点中重新选一个master
master挂了以后,不会在slave节点中重新选一个master
slave
一般都是只读的,并且接收主数据库同步过来的数据
缺点
缺点:
master节点在主从模式中唯一,若master挂掉,则redis无法对外提供写服务
主从模式的弊端就是不具备高可用性,当master挂掉以后,Redis将不能再对外提供写入操作,因此sentinel应运而生
master节点在主从模式中唯一,若master挂掉,则redis无法对外提供写服务
主从模式的弊端就是不具备高可用性,当master挂掉以后,Redis将不能再对外提供写入操作,因此sentinel应运而生
哨兵机制 sentinel 高可用
作用
监控redis集群的运行状况
功能
集群监控:负责监控 Redis master 和 slave 进程是否正常工作。
消息通知:如果某个 Redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。
配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。
当master挂了以后,sentinel会在slave中选择一个做为master,并修改它们的配置文件,其他slave的配置文件也会被修改,比如slaveof属性会指向新的master
当master挂了以后,sentinel会在slave中选择一个做为master,并修改它们的配置文件,其他slave的配置文件也会被修改,比如slaveof属性会指向新的master
总结:监控redis发生问题了,通知管理员,如果挂的是master,故障转移到slave,并通知客户端新的master地址
集群
sentinel因为也是一个进程有挂掉的可能,所以sentinel也会启动多个形成一个sentinel集群,sentinel之间也会自动监控
部署
sentinel最好不要和Redis部署在同一台机器,不然Redis的服务器挂了以后,sentinel也挂了
原理
哨兵选举
master选举
优缺点
具备高可用
当数据量过大到一台服务器存放不下的情况时,主从模式或sentinel模式就不能满足需求了,这个时候需要对存储的数据进行分片
当数据量过大到一台服务器存放不下的情况时,主从模式或sentinel模式就不能满足需求了,这个时候需要对存储的数据进行分片
子主题
数据分片
官方集群方式(服务器路由)
官方集群方式(服务器路由)
功能
子主题
没有采用一致性哈希算法,采用槽(slot)的概念,一共分为16384个槽;
请求发送到任一节点,都会被正确路由(在客户端的帮助下直接redirected到正确的redis节点)到正确的节点
请求发送到任一节点,都会被正确路由(在客户端的帮助下直接redirected到正确的redis节点)到正确的节点
方案说明
1. 通过哈希的方式,将数据分片,每个节点(主多从)均分存储一定哈希槽(哈希值)区间的数据,默认分配了16384 个槽位
2. 每份数据分片会存储在多个互为主从的多节点上
3. 数据写入先写主节点,再同步到从节点(支持配置为阻塞同步)
4. 同一分片多个节点间的数据不保持一致性
5. 读取数据时,当客户端操作的key没有分配在该节点上时,redis会返回转向指令,指向正确的节点
6. 扩容时需要把旧节点的数据迁移一部分到新节点
要点
每个redis要开放两个端口,一个对外提供使用,一个用于节点间通讯
节点间通讯采用cluster bus 的通信,用来进行故障检测、配置更新、故障转移授权。cluster bus 用了另外一
种二进制的协议, gossip 协议,用于节点间进行高效的数据交换,占用更少的网络带宽和处理时间
种二进制的协议, gossip 协议,用于节点间进行高效的数据交换,占用更少的网络带宽和处理时间
gossip协议
节点间内部通讯机制
集群元数据的维护有两种方式:集中式、Gossip 协议。redis cluster 节点间采用 gossip 协议进行通信。
优点
无中心架构支持动态扩容
具有哨兵模式的监控和故障转移能力
客户端不需要连接所有节点,连接任一节点即可
高性能,直接连接服务,免去了中间代理层
缺点
运维复杂,数据迁移需要人工干预
只能使用0号数据库
不支持批量操作
分布式逻辑和存储模块耦合
基于客户端分配
采用哈希算法将Redis数据的key进行散列,通过hash函数,特定的key会映射到特定的Redis节点上
优点
服务端彼此独立无相互关联,每个redis像独立的服务一样
非常容易线性扩展,系统灵活性强
缺点
sharding处理放到客户端,规模进一步扩大时给运维带来挑战
不支持动态增删节点。
服务端Redis实例群拓扑结构有变化时,每个客户端都需要更新调整。
连接不能共享,当应用规模增大时,资源浪费制约优化
服务端Redis实例群拓扑结构有变化时,每个客户端都需要更新调整。
连接不能共享,当应用规模增大时,资源浪费制约优化
基于代理服务器分片
代理解析客户端的数据,并将请求转发至正确的节点,最后将结果回复给客户端
特征
透明接入,业务程序不用关心后端Redis实例,切换成本低
Proxy 的逻辑和存储的逻辑是隔离的
代理层多了一次转发,性能有所损耗
业界开源方案
Twtter开源的Twemproxy
豌豆荚开源的Codis
cluster模式的出现就是为了解决单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器
分区
原因
分区可以让Redis管理更大的内存
没有分区,你最多只能使用一台机器的内存
分区方案
客户端分区
在客户端就已经决定数据会被存储到哪个redis节点或者从哪个redis节点读取
代理分区
代理根据分区规则决定请求哪些Redis实例
查询路由
客户端随机地请求任意一个redis实例,然后由Redis将请求转发给正确的Redis节点
缺点
涉及多个key的操作通常不会被支持
例如你不能对两个集合求交集,因为他们可能被存储到不同的Redis实例(实际上这种情况也有办法,但是不能直接使用 交集指令)
同时操作多个key,则不能使用Redis事务.
分区使用的粒度是key,不能使用一个非常长的排序key存储一个数据集
当使用分区的时候,数据处理会非常复杂
例如为了备份你必须从不同的Redis实例和主机同时收集RDB / AOF文件
分区时动态扩容或缩容可能非常复杂
Redis集群在运行时增加或者删除Redis节点,能做到最大程度对用户透明地数据再平衡,
但其他一些客户端分区或者代理分区方法则不支持这种特性。然而,有一种预分片的技术也可以较好的解决这个问题
但其他一些客户端分区或者代理分区方法则不支持这种特性。然而,有一种预分片的技术也可以较好的解决这个问题
子主题
子主题
常用工具
redisson
一个高级的分布式协调Redis客服端,能帮助用户在分布式环境中轻松实现一些Java的对象
功能简单,不支持字符串操作,不支持排序,事务,管道,分区等特性
jedis
redis的java客户端,提供比较全的redis命令操作
lettuce
主人信息
非关系型数据库
非关系型数据库特点
1、存储非结构化的数据,比如文本、图片、音频、视频。
2、表与表之间没有关联,可扩展性强。
3、保证数据的最终一致性。遵循 BASE(碱)理论。 Basically Available(基本 可用); Soft-state(软状态); Eventually Consistent(最终一致性)。
4、支持海量数据的存储和高并发的高效读写。
5、支持分布式,能够对数据进行分片存储,扩缩容简单。
2、表与表之间没有关联,可扩展性强。
3、保证数据的最终一致性。遵循 BASE(碱)理论。 Basically Available(基本 可用); Soft-state(软状态); Eventually Consistent(最终一致性)。
4、支持海量数据的存储和高并发的高效读写。
5、支持分布式,能够对数据进行分片存储,扩缩容简单。
常见的非关系型数据库
1、KV 存储,用 Key Value 的形式来存储数据。比较常见的有 Redis 和 MemcacheDB。
2、文档存储,MongoDB。
3、列存储,HBase。
4、图存储,这个图(Graph)是数据结构,不是文件格式。Neo4j。
5、对象存储。
6、XML 存储等等等等。
2、文档存储,MongoDB。
3、列存储,HBase。
4、图存储,这个图(Graph)是数据结构,不是文件格式。Neo4j。
5、对象存储。
6、XML 存储等等等等。
网站
官网介绍:https://redis.io/topics/introduction 中文网站:http://www.redis.cn
介绍 http://redisdoc.com/topic/persistence.html
介绍 http://redisdoc.com/topic/persistence.html
常用命令
存值set qingshan 2673
取值get qingshan
查看所有键 keys *
获取键总数 dbsize
查看键是否存在 exists qingshan
删除键 del qingshan jack
重命名键 rename qingshan pengyuyan
查看类型 type qingshan
取值get qingshan
查看所有键 keys *
获取键总数 dbsize
查看键是否存在 exists qingshan
删除键 del qingshan jack
重命名键 rename qingshan pengyuyan
查看类型 type qingshan
高并发带来的问题
雪崩
大量热点数据同时过期 (因为设置了相同的过期时 间,刚好这个时候 Redis 请求的并发量又很大,就会导致所有的请求落到数据库。)
解决方案
过期时间设置随机值,避免大量失效
永不过期
加互斥锁或者使用队列,针对同一个 key 只允许一个线程到数据库查询
给每个缓存增加是否失效标记,失效后马上刷新缓存 或者预先更新
穿透
请求数据库不存在的值,redis失去作用
解决方法
缓存空数据,设置短时间失效
不然的话数据库已经新增了这一条记录,应用也 还是拿不到值。
采用布隆过滤器
将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的
查询压力
查询压力
特点
1、如果布隆过滤器判断元素在集合中存在,不一定存在 2、如果布隆过滤器判断不存在,一定不存在
布隆过滤器把误判率默认设置为 0.03,也可以在创建的时候指定。
位图的容量是基于元素个数和误判率计算出来的。
存储 100 万个元素只占用了 0.87M 的内存,生成了 5 个哈希函数。
位图的容量是基于元素个数和误判率计算出来的。
存储 100 万个元素只占用了 0.87M 的内存,生成了 5 个哈希函数。
存在一定的误判率;过滤器越长误判率越小;哈希函数越多,效率越差,误判率越小
应用场景
因为要判断数据库的值是否存在,所以第一步是加载数据库所有的数据。在去 Redis 查询之前,先在布隆过滤器查询,如果 bf 说没有,那数据库肯定没有,也不用去查了。 如果 bf 说有,才走之前的流程。
问题 如何在海量元素中(例如 10 亿无序、不定长、不重复)快速判断一个元素是否存在?
在海量元素中快速判断一个元素是否存在
在海量元素中快速判断一个元素是否存在
原理
使用多次哈希函数计算每次得到位置,将位置标记为1,做有一个位置为0,则表示数据一定不存在
击穿
缓存中没有,数据库中有,(一般为缓存时间到期)
解决方案
热点数据永不过期
加互斥锁
缓存降级
服务出现异常或非核心业务影响核心业务,仍然保证核心系统能使用,可以根据关键数据判断实现缓存降级或者手动降级
目的
保障核心业务可用
为了防止Redis服务故障,导致数据库跟着一起发生雪崩问题。因此,对于不重要的缓存数据,可以采取服务降级策略
interview
为什么要放在内存中?
内存的速度更快,10wQPS
减少计算时间,减轻数据库压力
减少计算时间,减轻数据库压力
和memcache的区别
memcache只能存储KV、没有持久化机制、不支持主从复制、是多线程的
Redis为什么这么快?
纯内存结构
请求单线程
同步非阻塞IO
同步:用户线程和内核的交互方式
阻塞:线程调用内核IO操作
多路复用
多个TCP连接复用一个或多个线程
数据一致性保障?
流程
1、如果数据在 Redis 存在,应用就可以直接从 Redis 拿到数据,不用访问数据库。
2、如果 Redis 里面没有,先到数据库查询,然后写入到 Redis,再返回给应用。
2、如果 Redis 里面没有,先到数据库查询,然后写入到 Redis,再返回给应用。
子主题
子主题
方案
先更新数据库,再删除缓存
总之,对于后删除缓存失败的情况,我们的做法是不断地重试删除或异步删除,直到成功。保证数据的最终一致性
先删除缓存,再更新数据库
异常
异常情况:
1、删除缓存,程序捕获异常,不会走到下一步,所以数据不会出现不一致。
2、删除缓存成功,更新数据库失败。 因为以数据库的数据为准,所以不存在数据 不一致的情况。
1、删除缓存,程序捕获异常,不会走到下一步,所以数据不会出现不一致。
2、删除缓存成功,更新数据库失败。 因为以数据库的数据为准,所以不存在数据 不一致的情况。
看起来好像没问题,但是如果有程序并发操作的情况下:
1)线程 A 需要更新数据,首先删除了 Redis 缓存
2)线程 B 查询数据,发现缓存不存在,到数据库查询旧值,写入 Redis,返回
3)线程 A 更新了数据库 这个时候,Redis 是旧的值,数据库是新的值,发生了数据不一致的情况。
1)线程 A 需要更新数据,首先删除了 Redis 缓存
2)线程 B 查询数据,发现缓存不存在,到数据库查询旧值,写入 Redis,返回
3)线程 A 更新了数据库 这个时候,Redis 是旧的值,数据库是新的值,发生了数据不一致的情况。
延时双删的策略,在写入数据之后,再删除一次缓存
A 线程:
1)删除缓存
2)更新数据库
3)休眠 500ms(这个时间,依据读取数据的耗时而定)
4)再次删除缓存
1)删除缓存
2)更新数据库
3)休眠 500ms(这个时间,依据读取数据的耗时而定)
4)再次删除缓存
一个字符串类型的内存最大容量
512M
常见性能问题和解决方案
1. Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化。
2. 如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次(可配置为每执行一个命令就持久化一次)。
3. 为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内。
4. 尽量避免在压力较大的主库上增加从库
5. Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。
延时队列的实现
使用时间戳做score, 消息内容作为key,调用zadd来生产消息,消费者使用zrangbyscore获取n秒之前的数据做轮询处理。
使用过Redis做异步队列么,你是怎么用的?有什么缺点?
使用过 Redis 做异步队列么,你是怎么用的?答:一般使用 list 结构作为队列,rpush 生产消息,lpop 消费消息。当 lpop 没有 消息的时候,要适当 sleep 一会再重试。
如果对方追问可不可以不用 sleep 呢?list 还有个指令叫 blpop,在没有消息的时候,它会阻塞住直到消息到来。
如果对 方追问能不能生产一次消费多次呢?使用 pub/sub 主题订阅者模式,可以实现 1:N 的消息队列。
当发布者通过PUBLISH 命令向chinnel发布命令时,订阅该频道的客户端都会受到此消息。
如果对方追问 pub/sub 有什么缺点?在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如 RabbitMQ等。
如果对方追问 redis 如何实现延时队列?我估计现在你很想把面试官一棒打死如果你手上有一根棒球棍的话,怎么问的这 么详细。但是你很克制,然后神态自若的回答道:使用 sortedset,拿时间戳作为 score,消息内容作为 key 调用 zadd 来生产消息,消费者用 zrangebyscore 指令 获取 N 秒之前的数据轮询进行处理。到这里,面试官暗地里已经对你竖起了大拇 指。但是他不知道的是此刻你却竖起了中指,在椅子背后。
什么是redis
Remote Dictionary Server 远程字典服务
是一个开源的基于C语言编写的nosql
0 条评论
下一页
为你推荐
查看更多