Redis知识点整理

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,和Memcached类似;它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型);同时,还支持地理位置GEO和Bitmap扩展类型。

Redis之所以这么受欢迎,得益于它的性能,说到性能又不得不提它的单线程设计。那为什么redis采用单线程还这么高效呢?主要由以下原因:

  1. 减少上下文切换时间
  2. 纯内存访问
  3. 非阻塞IO,使用epoll

数据类型

字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
set key xx ex[seconds] | px [milliseconds] [nx |xx] # 如何实现分布式共享锁
setex seconds key
setnx key
setxx key

get key
del key

mset key1 value1 [key2 value2 …] # mset 与 set 之间最大的差异和性能改善在哪儿?
mget key1 [key2 …]

append key value

exists key
expire key seconds

strlen key

getset key value

setrange key offset value
getrange key start end

type key
object encoding key

incr key
decr key

哈希

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
hset key field value
Hget key field
Hdel key field [field …]

hmset key field value [field value …]
hmget key field [field …]

hexists key field

hkeys key
hvals key
hgetall key

hstrlen key field
hlen key

列表

特征:

  1. 列表中元素有序
  2. 列表中元素可重复
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
lpush key value [value …]
rpush key value [value …]

lrange start end # lrange key 0 -1
linsert key before | after pivot value
lindex key index

llen key

lpop key
rpop key

ltrim key count value # count>0 从左到右删除最多count个, count<0 从右到左删除最多count个,count=0 删除所有
ltrim key start end # 保留start->end

lset key index value

blpop key timeout
brpop key timeout

集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sadd key element [element …]
srem key element [element …]

scard key # 计算元素个数
sismember key element # 判断元素是否在集合中
srandmemeber key [count] # 随机从集合中返回指定个数值(不会删除)
spop key # 从集合中随机弹出元素(随即删除)

sinter key [key ...] # 交集
suinon key [key ...] # 并集
sdiff key [key ...] # 差集


sinterstore destination key [key ...] # 交集集合保存
suionstore destination key [key ...] # 并集集合保存
sdiffstore destination key [key ...] # 差集集合保存

有序集合

特征:

  1. 保留不可重复特征
  2. 给每个元素设置一个score作为排序的依据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
zadd key score member [score member ...]
zcard key

zscore key member # 计算某个成员的分数
zrank key member # 从低到高排名
zrevrank key member # 从高到低排名

zrem key member [member ...] # 删除成员
zincrby key increment member # 增加成员分数

zrange key start end [withscores] # 返回指定排名范围的成员
zrevrange key start end [withscores]

zrangebyscore key min max [withscores] [limit offset count] # 返回指定分数范围的成员
zrevrangebyscore key max min [withscores] [limit offset count]

zcount key min max # 返回指定分数范围的成员个数

zremrangebyrank key start end # 删除指定排名内的升序元素
zremrangebyscore key min max # 删除指定分数范围的成员

其他

包括用于计算地理位置的GEO 和 BITMAP 两种扩展类型。

键管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
dbsize

rename key newKey
randomkey # 随机返回一个key

expire key second
persist key
ttl key

move key db

dump key # 序列化为RDB格式
restore key ttl value

flushdb # 清除当前数据库
flushall # 清除所有数据库

日常运维

慢查询

1
2
3
4
5
config set slowlog-log-slower-than 20000    # 慢查询标准为慢于20000微秒
config set slowlog-max-len 1000 # 日志最大条数

slowlog get [n] # 读取慢查询日志
slowlog len # 获取慢查询日志长度

事务

1
2
3
4
multi
xxx
xxx
exec/discard

数据持久化

  • RDB快照手动触发时,save和bgsave的差异?
  • AOF以独立日志方式记录每次写操作,重启时重放以恢复数据。

触发方法

  1. 手动bgrewriteaof
  2. 自动根据auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage确定自动触发机制

持久化流程

命令写入 -> AOF缓冲区 -> AOF文件 -> rewrite -> 重启(load)

执行重写后,为什么AOF文件会变小?

  1. 干掉一些中间状态的数据,比如set之后又del的数据;
  2. expire已经timeout的数据,不再写入;
  3. 多条命令可以合并为一条;

三种AOF缓冲区同步文件策略

  • always
  • everysec
  • none

复制相关

1
2
3
slave of host port
slave of no one
info replication

默认情况下, 从节点使用 slave-read-only=yes 配置为只读模式。

哨兵模式

redis sentinel是一个分布式架构,其中包含若干个Sentinel节点和Redis数据节点,每个Sentinel节点会对数据节点和其余Sentinel节点进行监控,当它发现节点不可达时,会对节点做下线标识。

如果被标识的是主节点,它还会和其他Sentinel节点进行“协商”,当大多数 Sentinel节点都认为主节点不可达时,它们会选举出一个Sentinel节点来完成自动故障转移的工作,同时会将这个变化实时通知给Redis应用方。

哨兵的流程:

  1. 监控并发送报文给各自的节点;
  2. 发现主观下线;
  3. 询问,并投票,客观下线;
  4. 领导者节点选举->raft(基本为谁最早发现某个redis节点主观下线,就会发起投票,然后的票就会最多,然后成为切换该主redis的领导者);
  5. 故障转移;选出新的老大(在从节点中,过滤不健康的,然后基于优先级->复制偏移量->runid

集群方案

redis cluser采用虚拟槽分区,所有的键根据哈希函数映射到0~16383整数槽内,计算公式: slot = CRC16(key)& 16383

集群限制

  1. 不支持多个db
  2. Key的批量操作有限,比如mset

节点握手

1
2
3
cluster meet {ip} {port}
cluster nodes
cluster info

分配槽

1
cluster addslots {0…5555}

从节点设置

1
cluster replicate {master node id}

缓存穿透解决办法

  1. 缓存空对象
  2. 布隆过滤器

值得深入思考的问题

  1. redis如何实现消息队列?
  2. 如何使用redis实现每分钟获取验证码的次数不超过5次?
  3. redis的订阅与发布适合用来做消息队列吗?为什么?
  4. 如果一个key设置了expire时间,get操作之后,expire会发生变化吗?
  5. 关系型数据库存储与hash散列存储的差异性在哪儿?
  6. 将数据直接序列化后使用string存到redis和将数据按照hash存到redis两者的优缺点?
  7. 如何通过redis快速计算出具有共同兴趣爱好的一类人?
  8. 如何通过redis计算被点赞数的用户排名?
  9. 当系统中同时存在AOF和RDB文件时,系统重启默认有限加载哪一个?
  10. 哨兵模式下,客户端连接的是redis节点,还是哨兵节点?
  11. 缓存雪崩后,重建缓存可能会被很多程序调用到,这个时候如何采用较好的方法避免出现大家都去重建缓存呢?
0%