史上最全redis面试49题哨兵、复制、事务、集群、持久化
- 哨兵、复制、事务、集群、持久化
redis主要有哪些功能
- 哨兵和复制(sentinel and replication):
sentinel可以管理多个redis服务器,它提供监控、提醒、故障转移等功能
replication则是可以让一个redis服务器拥有一个或多个配备服务器
redis也是利用这两个功能保证了服务的高可用性 - 事务:
redis支持事务,但是又不完全支持,因为它没有回滚机制 - LUA脚本
在事务的基础上,如果我们需要一次性执行更复杂的操作(包含一些逻辑判断),则lua就可以排上用场了 - 持久化
redis的持久化指的是redis会把内存中的数据写入到磁盘中,在redis重新启动的时候加载这些数据,
从而最大程度的降低缓存丢失带来的影响 - 集群
单台服务器的资源总是有限的,CPU资源和IO资源我们可以通过主从复制,读写分离,把一部分CPU和IO的压力转移到从服务器上,这有点类似mysql数据库的主从同步
单台实例内存容量也是有限的,可以通过将数据按照一定的规则分配到多台服务器上,横向扩展内存容量
redis支持哪几种数据类型
string:最基本的数据类型,二进制安全的字符串,最大512M
list:按照添加顺序保持顺序的字符串列表
set:无序的字符串集合,不包含重复的元素
zset:已排序的字符串集合
hash:key-value对的一种集合
redis常用命令
-
keys 键命令
- keys 查询所有key
- type 查找key的类型
- del 删除一个key
- expire 给key设置过期时间
- ttl 查询key还有多长时间过期
- exists 查询key是否存在
-
string 字符串命令
- set 设置一个字符串
- setex 设置一个带过期时间的字符串
- mset 设置多个字符串
- get 获取一个字符串
- mget 获取多个字符串
- append 给字符串追加内容
-
list 列表命令---有序的
- lpush 从列表头部插入
- rpush 从列表尾部插入
- linsert 从列表中间插入
- llen 统计列表长度
- lindex 按索引取出一个元素
- lrange 取出多个元素
- lset 按索引更新键对应的值
- lrem 按照值删除指定个数的元素
- lpop 从列表头部弹出一个元素
- rpop 从列表尾部弹出一个元素
- lpushx 从已有的列表头部插入一个元素,列表不存在不会创建
- rpushx 从已有的列表尾部插入一个元素,列表不存在不会创建
- ltrim 从列表中截取一部分
-
set 集合命令---无序的,member不可以重复
- sadd 向集合中添加元素
- smembers 显示所有集合成员
- srem 删除集合成员
- sismember 判断某个元素是否是集合中的成员
- srandmember 从集合中随机选取一个成员
-
zset 有序集合命令---score可以重复,member不可以重复
- zadd 向有序集合中添加元素
- zrange 从有序集合中获取元素
- zrangebyscore 从有序集合中通过score获取元素
- zrem 从有序集合中删除元素
- zremrangebyscore 按照score删除元素
- zrank 获取有序结合中元素的索引
- zremrangebyrank 按照索引删除元素
- zrevrange 反转有序集合
-
hash 哈希命令
- hset 设置哈希值的单个键值对
- hmset 设置哈希值的多个键值对
- hget 获取哈希值的单个键值对
- hmget 获取哈希值的多个键值对
- hdel 删除哈希值中键值对
- hkeys 获取哈希值中的所有键
- hvals 获取哈希值中的所有值
- hexists 查看哈希值中的某个键是否存在
- hgetall 获取哈希值中的所有键值
- hlen 获取哈希中的键值对个数
- hsetnx 和hset有点类似,不同之处在于当key对应的field存在时就不做操作了,只有field不存在时才会增加
redis是单进程单线程的?
redis是单进程单线程的,redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销
redis为什么是单线程的?
多线程会涉及到锁,而且多线程的上下文切换会消耗CPU资源,CPU不是redis的瓶颈,
redis的瓶颈最有可能是机器内存和网络宽带,单线程无法发挥多核CPU性能,可以通过在单机开启多个redis实例来解决
其它开源软件模型
Nginx: 多进程单线程模型
Memcached: 单进程多线程模型
使用redis的优势
- redis是基于内存的,读写速度极快,类似于hashmap, 查找和操作的时间复杂度是O(1)
- 有丰富的数据类型:string、list、set、zset、hash
- 支持事务
- 丰富的特性:可用于缓存,消息,设置key的过期时间, 过期后自动删除
redis单点吞吐量
单点TPS达到8万/s, QPS达到10万/s
什么是QPS:每秒钟处理的请求数量
什么是TPS: 每秒钟处理的事务数量(一个事务在分布式系统中,可能对应多个请求)
redis相比Memcached有哪些优势
- memcached所有的值均是简单的字符串,redis支持丰富的数据类型
- redis比memcached速度快很多
- redis支持数据的持久化
- redis支持数据备份,即master-slaver模式
redis有哪几种数据淘汰策略
- noeviction: 当redis的maxmemory达到最大值继续写入时,不会删除键,直接返回错误
- allkeys-lru: 当redis的maxmemory达到最大值继续写入时, 随机选取maxmemory-examples个key, 然后删除最近最少使用的key
- allkey-random: 当redis的maxmemory达到最大值继续写入时, 随机选取maxmemory-examples个key, 然后随机删除一个key
- volatile-lru: 当redis的maxmemory达到最大值继续写入时, 从带有过期时间的key中随机选取maxmemory-examples个key, 删除最近最少使用的key
- volatile-random: 当redis的maxmemory达到最大值继续写入时, 从带有过期时间的key中随机选取maxmemory-examples个key, 随机删除一个key
- volatile-ttl: 当redis的maxmemory达到最大值继续写入时, 从带有过期时间的key随机选取maxmemory-examples个key, 删除最先过期的key
redis淘汰数据时还会同步到aof
redis集群方案应该怎么做,都有哪些方案?
- twemproxy
- codis, 目前用的最多的集群方案,和twemproxy基本一致,但它支持在节点数量改变的情况下,就节点数据可以恢复到新hash节点
- redis cluster3.0自带的集,特点在于它的分布式算法不是一致性hash,而是hash槽的概念,以及自身节点设置从节点
redis读写分离模型
通过增加slave DB的数量,读的性能可以线性增长,为了避免master DB单点故障,集群一般都会采用两台master DB做双机热备
所以整个集群读和写的可用性都非常高
读写分离架构的缺陷在于,不管是master还是slaver,每个节点都需要保存完整数据,如果数据量很大的情况下,
集群的扩展能力还是受限于单个节点的存储能力,而且对于write-intensive的应用,读写分离的架构并不合适
redis数据分片模型
为了解决读写分离模型的缺陷,可以将数据分片模型应用进来,
可以将每个节点都看成独立的master,然后通过业务实现数据分片
- 结合上面两种模型,可以将每个master设置成由一个master多个slaver组成的模型
- 通过读写分离模型+数据分片模型大大增强了redis集群的数据存储能力和读写并发能力
redis提供了哪几种持久化方式
RDB持久化方式能够在指定的时间间隔对你的数据进行快照存储
AOF持久化方式是记录每次对服务器的写操作,当服务器重启的时候会重新执行这些命令恢复原始数据
当然也可以同时开启这两种持久化方式,当吴福气重启的时候会有限加载AOF文件来恢复原始数据
因为通常情况下AOF文件保存的数据要比RDB中的数据要完整
redis常见的性能问题和解决方案
- master最好不要做任何持久化工作,如RDB内存快照或AOF日志文件
- 为了主从复制的速度与稳定性,master和slaver最好字啊同一个局域网内
- 尽量避免在压力很大的主库上增加从库
- 主从复制不要用图状结构,最好用单向链表结构更稳定
redis哈希槽的概念
redis cluster3.0没有使用一致性hash,而是使用了hash槽,当需要在redis集群中放入一个key-value时
根据CRC16(key) mod 16384的值,决定将一个key放入哪个桶中
redis集群最大节点个数是多少
redis集群预先分布好16384个桶(哈希槽)
redis集群会有写操作丢失吗?为什么
redis并不能保证数据的强一致性,在实际中集群有可能会有写丢失操作
redis集群之间是如何复制的
异步复制
redis如何做内存优化
尽可能使用散列表(hash类型),散列表使用的内存非常小,所以应该尽可能将数据模型抽象到散列表里面
比如web系统中的一个用户对象,不要将用户名、姓氏、邮箱、密码都设置单独的key
而是把这个用户的所有信息存储到一张散列表里面, 大大节省内存
redis的回收进程如何工作的
一个客户端运行了新命令,添加了新数据,检查redis的内存使用达到maxmemory最大值时,
就会使用默认的LRU算法进行最近最少使用进行淘汰回收
redis回收使用的什么算法
LRU算法
redis有哪些应用场景
session共享(单点登录)
页面缓存
消息队列
排行榜/计数器
发布/订阅