相关文章:
【Redis面试】基础题总结(上)
【Redis面试】基础题总结(中)
有关redis基础知识见专栏:Redis
set:
集合中的元素是无序、不可重复的,一个集合最多能存储232-1个元素;
集合除了支持对元素的增删改查之外,还支持对多个集合取交集、并集、差集。
zset:
有序集合保留了集合元素不能重复的特点;
有序集合会给每个元素设置一个分数,并以此作为排序的依据;
有序集合不能包含相同的元素,但是不同元素的分数可以相同。
很多时候,要确保事务中的数据没有被其他客户端修改才执行该事务。Redis提供了watch命令来解决这类问题,这是一种乐观锁的机制。客户端通过watch命令,要求服务器对一个或多个key进行监视,如果在客户端执行事务之前,这些key发生了变化,则服务器将拒绝执行客户端提交的事务,并向它返回一个空值。
列表是线性有序的数据结构,它内部的元素是可以重复的,并且一个列表最多能存储2^32-1个元素。列表包含如下的常用命令:
lpush/rpush:从列表的左侧/右侧添加数据;
lrange:指定索引范围,并返回这个范围内的数据;
lindex:返回指定索引处的数据;
lpop/rpop:从列表的左侧/右侧弹出一个数据;
blpop/brpop:从列表的左侧/右侧弹出一个数据,若列表为空则进入阻塞状态。
热点数据不设置过期时间,使其达到“物理”上的永不过期,可以避免缓存击穿问题;
在设置过期时间时,可以附加一个随机数,避免大量的key同时过期,导致缓存雪崩。
通用指令是部分数据类型的,都可以使用的指令,常见的有:
KEYS:查看符合模板的key,不建议在生产环境设备上使用(因为redis是单线程的,只能同时处理一条指令,如果数据量大的情况下,查询所有会造成巨大的性能消耗,产生堵塞)。
DEL:删除一个指定的key。
EXISTS:判断key是否存在。
EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除。
TTL:查看一个KEY的剩余有效期
针对热点数据进行缓存
对于特定限时数据的存放
针对带热点权值数据的排序list
分布式锁
redis处理网络请求采用单线程模型,而memcache采用多线程异步IO的方式
redis支持数据持久化,memcache不支持
redis支持的数据格式比memcache更多
优点:
基于内存操作,内存读写速度快。
支持多种数据类型,包括String、Hash、List、Set、ZSet等。
支持持久化。Redis支持RDB和AOF两种持久化机制,持久化功能可以有效地避免数据丢失问题。
支持事务。Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
支持主从复制。主节点会自动将数据同步到从节点,可以进行读写分离。
Redis命令的处理是单线程的。Redis6.0引入了多线程,需要注意的是,多线程用于处理网络数据的读写和协议解析,Redis命令执行还是单线程的。
缺点:
对结构化查询的支持比较差。
数据库容量受到物理内存的限制,不适合用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的操作。
Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。
Redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器。它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。
文件事件处理器使用I/O多路复用(multiplexing)程序来同时监听多个套接字, 并根据套接字目前执行的任务来为套接字关联不同的事件处理器。
当被监听的套接字准备好执行连接accept、read、write、close等操作时, 与操作相对应的文件事件就会产生, 这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。
虽然文件事件处理器以单线程方式运行, 但通过使用 I/O 多路复用程序来监听多个套接字, 文件事件处理器既实现了高性能的网络通信模型, 又可以很好地与 redis 服务器中其他同样以单线程方式运行的模块进行对接, 这保持了 Redis 内部单线程设计的简单性。
单机版:单机部署,单机redis能够承载的 QPS 大概就在上万到几万不等。这种部署方式很少使用。存在的问题:
1、内存容量有限 2、处理能力有限 3、无法高可用。
主从模式:一主多从,主负责写,并且将数据复制到其它的 slave 节点,从节点负责读。所有的读请求全部走从节点。这样也可以很轻松实现水平扩容,支撑读高并发。master 节点挂掉后,需要手动指定新的 master,可用性不高,基本不用。
哨兵模式:主从复制存在不能自动故障转移、达不到高可用的问题。哨兵模式解决了这些问题。通过哨兵机制可以自动切换主从节点。master 节点挂掉后,哨兵进程会主动选举新的 master,可用性高,但是每个节点存储的数据是一样的,浪费内存空间。数据量不是很多,集群规模不是很大,需要自动容错容灾的时候使用。
Redis cluster:服务端分片技术,3.0版本开始正式提供。Redis Cluster并没有使用一致性hash,而是采用slot(槽)的概念,一共分成16384个槽。将请求发送到任意节点,接收到请求的节点会将查询请求发送到正确的节点上执行。主要是针对海量数据+高并发+高可用的场景,如果是海量数据,如果你的数据量很大,那么建议就用Redis cluster,所有主节点的容量总和就是Redis cluster可缓存的数据容量。
通常我们会将含有较大数据或含有大量成员、列表数的Key称之为大Key。
以下是对各个数据类型大key的描述:
value是STRING类型,它的值超过5MB
value是ZSET、Hash、List、Set等集合类型时,它的成员数量超过1w个
上述的定义并不绝对,主要是根据value的成员数量和大小来确定,根据业务场景确定标准。
怎么处理:
当vaule是string时,可以使用序列化、压缩算法将key的大小控制在合理范围内,但是序列化和反序列化都会带来更多时间上的消耗。或者将key进行拆分,一个大key分为不同的部分,记录每个部分的key,使用multiget等操作实现事务读取。
当value是list/set等集合类型时,根据预估的数据规模来进行分片,不同的元素计算后分到不同的片。
Redis 官方站提出了一种权威的基于 Redis 实现分布式锁的方式名叫 Redlock,此种方式比原先的单节点的方法更安全。它可以保证以下特性:
安全特性:互斥访问,即永远只有一个 client 能拿到锁
避免死锁:最终 client 都可能拿到锁,不会出现死锁的情况,即使原本锁住某资源的 client 挂掉了
容错性:只要大部分 Redis 节点存活就可以正常提供服务
redis客户端执行一条命令分4个过程: 发送命令、命令排队、命令执行、返回结果。使用pipeline可以批量请求,批量返回结果,执行速度比逐条执行要快。
使用pipeline组装的命令个数不能太多,不然数据量过大,增加客户端的等待时间,还可能造成网络阻塞,可以将大量命令的拆分多个小的pipeline命令完成。
原生批命令(mset和mget)与pipeline对比:
原生批命令是原子性,pipeline是非原子性。pipeline命令中途异常退出,之前执行成功的命令不会回滚。
原生批命令只有一个命令,但pipeline支持多命令。