Redis简介
Redis是开源的(BSD许可),数据结构存储于内存中,被用来作为数据库,缓存和消息代理。它支持多种数据结构,例如:字符串(string),哈希(hash),列表(list),集合(set),带范围查询的排序集合(zset),位图(bitmap),hyperloglog,带有半径查询和流的地理空间索引(geospatial)。 Redis具有内置的主从复制机制,Lua脚本,事务和不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster自动分区提供高可用性。
Redis各数据结构常用命令
String 类型常用命令
命令行 | 含义 |
set key value | 赋值key的值为value |
get key / del key | 获取key的value值 / 删除key |
expire key seconds | 设置key在seconds秒后过期 |
setex key seconds value | SET + EXPIRE的组合指令 |
ttl key | 查看key还有多久过期 |
setnx key value | 如果key不存在,才新增key和value |
strlen key | 计算指定key的值的长度 |
incr key | value值加1 |
incrby key numbers | 指定增加值,numbers可以是负值 |
mset key1 value1 key2 value2 ... | 批量添加 |
mget key1 key2 key3 … | 批量获取 |
List类型常用命令
命令行 | 含义 |
lpush key value1 value2 | 左侧插入value |
rpush key value1 value2 | 右侧插入value |
lrange key startIndex endIndex | 查看指定元素,下标从0开始,-1为倒数第一个 |
lpop key | 左侧弹出value |
rpop key | 右侧弹出value |
llen key | 查看key的长度 |
lindex key index | 查看列表中某个index对应的value值 |
ltrim key startIndex endIndex | 仅保留某区间的列表,其余元素全被删除 |
Set类型常用命令
命令行 | 含义 |
sadd key value1 value2 | 添加元素到集合中 |
smembers key | 查看集合中的所有元素 |
sismember key value | 查看value是否在集合中 |
scard key | 查询集合的长度 |
spop key | 取出集合中的一个元素 |
del key | 删除集合 |
Zset类型常用命令
命令行 | 含义 |
zadd key score1 value1 score2 value2 | 添加元素到有序集合中 |
zscore key value | 查看value的score值,输出score>=负无穷,score<=正无穷的所有元素 |
zrange key 0 -1 [withscores] | 正序输出 |
zrangebyscore key -inf +inf [withscores] | 正序输出 |
zrevrange key 0 -1 [withscores] | 倒序输出 |
zcard key | 查看key中的元素个数 |
zrangebyscore key minScore maxScore | 获得key中score>=minScore 且score<=maxScore 的元素,正序排列 |
zrevrangebyscore key maxScore minScore | 同上,倒序排列 |
zrem key value | 删除key中的元素value |
Hash类型常用命令
命令行 | 含义 |
hset key name value | 添加属性元素name和value到key中 |
hget key name | 查看key的name值 |
hmset key name1 value1 name2 value2 | 批量添加key的属性元素 |
hmget key name1 name2 | 批量获取key的属性元素 |
hlen key | 获得key的属性元素个数 |
hgetall key | 查询key中的所有元素 |
Redis的持久化
RDB
制文件,对应文件为dump.rdb,因为它保存在磁盘上,所以可以用它来还原数据库中的数据。
手动执行RDB保存有两个命令:
SAVE命令: 阻塞Redis服务器进程,直到RDB文件生成完毕,都会一直处于阻塞状态,不能处理任何的Redis命令请求;
BGSAVE命令: fork一个子进程来生成RDB文件,Redis服务器进程不受影响,可以继续处理命令请求。
当服务器启动的时候,RDB自动执行加载,没有专门的命令来加载RDB文件。只要Redis启
动时检测到RDB文件的存在,那么就会自动载入RDB文件。加载过程中,会一直处于阻塞状
态,直到加载完毕为止。由于 AOF文件的更新频率一般比RDB文件的更新频率高,所以,如
果服务期开启了AOF持久化功能,那么就优先加载AOF文件,否则,加载RDB文件。
AOF
auto-aof-rewrite-min-size:表示运行AOF重写时文件最小体积,默认为64M
auto-aof-rewrite-percentage:代表当前AOF文件空间(aof_current_size)和上一次重写后AOF文件空间(aof_base_size)的比值。
重写后的AOF文件为什么可以变小?
- 进程内已经超时的数据不再写入文件。
- 旧的AOF文件含有无效命令,如del key1,hdel key2,srem keys,set a 111,set a222
- 重写使用进程内数据直接生成,这样新的AOF文件只保留最终的数据的写入名。
- 多条写命令可以合并为1个。如 lpush list a,lpush list b,lpush list c,可以转换为lpush list a b c .为了防止单条命令过大造成客户端缓冲区溢出,
- 对于list,set,hash,zset类数据类型,以64个元素为界限拆分为多条。
Redis主从复制
主从复制的好处:
- 数据冗余: 主从复制实现了数据的备份,实际上提供了数据冗余的实现方式。
- 故障恢复: 当主节点出现异常时,可以由从节点提供服务,实现快速的故障恢复,实际上提供了服务冗余的实现方式。
- 负载均衡: 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器的负载;在写少读多的业务场景下,通过多个从节点分担读负载,可以大大提高Redis服务器是并发量。
- 高可用: 哨兵配合主从复制,可以是实现Redis集群的高可用.
Redis的主从复制可以分为两个阶段:sync阶段(首次启动的全量同步)和commandpropagate阶段(后续的增删改命令同步).
但是每次主从节点重新链接都要全量同步也是很耗费资源的, 后续Redis2.8做出优化, 引入了 psync指令来代替sync指令。psync指令会根据不同的情况,来确定执行全量重同步还是部分重同步。
主从同步防止数据丢失---复制偏移量
Redis哨兵模式
哨兵本质就是一个Redis实例节点。哨兵模式是一种特殊的模式,它能够后台监控主机是否故障,如果主机故障了,则根据投票数自动将Slave节点转换为新的Master节点。 首先Redis提供了哨兵的命令,哨兵是一个独立的进程,会独立的运行。它的原理是:哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
选举流程
当一个Sentinel判断主节点不可用的时候,会首先进行“主观下线”。此时,这个Sentinel
通过sentinel is-masterdown-by-addr指令获取其他哨兵节点对主节点的判断,如果当
前哨兵节点对主节点主观下线的票数超过了我们定义的quorum值,则主节点被判定为
“客观下线”。
Sentinel节点会从原主节点的从节点中选出一个新的主节点,选举流程如下:
① 首先,过滤掉所有主观下线的节点。
② 然后,选择slave-priority最高的节点,如果有则返回,没有就继续下面的流程。
③ 选择出复制偏移量offset最大的节点,如果有则返回,没有就继续下面的流程。
④ 选择run_id最小的节点,其中,run_id表示服务器运行 ID。
⑤ 在选择完毕后,Sentinel节点会通过SLAVEOF NO ONE命令让选择出来的从节点成为主
节点,然后通过SLAVEOF命令让其他的节点成为该节点的从节点。
Redis Cluster集群
Redis3.0开始引入了去中心化分片集群Redis Cluster。
传统的Redis集群是基于主从复制+哨兵的方式来实现的。但是集群中都只有一个主节点提供写服务。
Redis Cluster则采用多主多从的方式,支持开启多个主节点,每个主节点上可以挂载多个从节点。
Cluster会将数据进行分片(虚拟节点 + 一致性哈希),将数据分散到多个主节点上,而每个主节点都可以对外提供读写服务。这种做法使得Redis突破了单机内存大小限制,扩展了集群的存储容量。并且Redis Cluster也具备高可用性,因为每个主节点上都至少有一个从节点,当主节点挂掉时,Redis Cluster 的故障转移机制会将某个从节点切换为主节点。
Redis Cluster是一个去中心化的集群,每个节点都会与其他节点保持互连,使用gossip协议来交换彼此的信息,以及探测新加入的节点信息。并且Redis Cluster无需任何代理,客户端会直接与集群中的节点直连。
数据分片:一个集群包含16384个哈希槽(hashslot)也就是16384个虚拟节点。将虚拟节点分配给实际节点,然后由虚拟节点来抢占由整个哈希值空间组织成的一个虚拟的圆环.
Redis面试题
分布式锁 (getset命令/lua脚本)
缓存穿透(Redis和数据库都没有的数据) 解决方案:
1.将数据库返回的空数据也缓存到Redis, 并设置合理过期时间
2. 布隆过滤器(它可以判断某个数据一定不存在,但是无法判断一定存在)
缓存击穿(某热点数据在过期的情况下有大量高并发请求) 解决方案:
1. 设置热点数据永不过期
2. 加锁,过期时只允许一个线程去数据库查询并缓存
缓存雪崩(大量数据同一时间过期或者Redis宕机) 解决方案:
1.搭建集群
2.服务限流降级
3.将数据的过期时间尽量打散, 别集中在同一时间