欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Redis深度探险知识总结

程序员文章站 2022-06-24 18:35:37
1.数据结构String:get/set,mget,incr,expire,setnx,setexlist: rpush/lpush,lpop/rpop,llen,lrange,ltrimhashsethset高级数据结构bitmapsHyperLogLog布隆过滤器GEOPubSub2. 分布式锁并发保证数据原子性(操作不会被线程调度打断)关键命令 setnx,del死锁触发条件:当del没有被调用解决方案:setnx和expire可以一起执行(超时锁会过期,...

1.数据结构

  • String:get/set,mget,incr,expire,setnx,setex
  • list: rpush/lpush,lpop/rpop,llen,lrange,ltrim
  • hash
  • set
  • hset
    高级数据结构
  • bitmaps
  • HyperLogLog
  • 布隆过滤器
  • GEO
  • PubSub
  • Stream

2. 分布式锁

并发保证数据原子性(操作不会被线程调度打断)
关键命令 setnx,del

死锁

触发条件:当del没有被调用
解决方案:

  1. setnx和expire可以一起执行(超时锁会过期,就释放了锁)
  2. 乐观锁(设置一个随机数)–>释放时校验随机数是否一致

3.延时队列

基于list数据结构(本质时linkedlist)

流程: 将操作放入list队列中,处理完成再获取消息

队列空了怎么办(陷入pop死循环)

  1. 线程睡一会(多个操作会导致反应过慢)
  2. 延迟队列(将请求放入延时队列,过一会再执行)
  3. 抛出异常,让用户等一会

4.限流

简单限流

使用zset的score值对时间戳进行排序
可以使用pipeline提高效率

漏斗限流

最常用的一种限流方式
Redis插件 Redis-Cell

解释:如漏斗一样,堵住会变满,放开就下流。漏嘴流水速率小于灌水的速率,漏斗会变满,需要暂停并腾空漏斗。

5.堵塞

这keys *堵塞

缺点

  1. 没有分页
  2. 时间复杂度为On,容易卡顿

SCAN

  1. 不会堵塞
  2. 可分页
  3. 提供匹配功能
  4. 有游标
  5. 结果会重复
  6. 结束游标值为0

遍历顺序:高位进位加法

定位大key(一般为hash结构)
命令: redis-cli -h 127.0.0.1 -p 7001 --bigkeys -i 0.1

6.IO模型

  1. 单线程
  2. 内存数据库
  3. 多路复用(读写事件多路处理)
  4. 非阻塞IO
    1. 套接字
    2. 指令队列(每个客户端套接字关联一个指令队列,顺序处理,先到先服务)
    3. 响应队列(每个客户端套接字关联一个响应队列,可以将结果返回,队列为空时弹出连接,证明客户端已经没有工作)
    4. 定时任务

7.RESP协议

  1. 字符串 +开头
  2. 多行字符串 $开头
  3. 整数 :: 开头
  4. 错误消息 - 开头
  5. 数组 * 开头

AOF持久化就是记录的是写操作 ,可进去查看

8.持久化

快照

原理:Redis单线程不仅需要负责线上请求还要负责IO操作,严重拖垮服务器性能,需要同时负责请求和IO操作,Redis使用COW(Copy on write)来实现
fork(多进程):
调用glib函数创建一个子进程负责IO操作,共享父进程内存中的代码段和数据段。父进程就负责请求和对内存的修改
为什么叫快照:
子进程看到的数据没有变化,所以叫快照,可以安心写入磁盘中

AOF原理

因为快照记录数据不完全
作用:只记录写操作,就可以重放数据到内存中

缺点:AOF日志越来越多,需要缩身
解决方案:提供bgrewriteaof指令 开辟了一个子进程将写操作序列化到新的AOF中,增量AOF会追加到新的AOF文件中

fsync:
问题:如果掉电导致宕机AOF没有来得及写入怎么办?
答案:提供fsync保证aof数据不丢失,但是很慢!
两种策略:1.永不fsync,不安全
2.fsync,生产环境一般不会使用

混合持久化

重启时,先加载rdb,再加载aof,提高效率

问题:为什么Redis只适合缓存
1.无法大量存储,不能保证数据安全
2.复杂数据不易存,不能存表关联关系
3.sfsnc使redis比mysql效率慢

8.管道

pipeline将多个指令操作押入管道中,客户端只请求一次到服务器中,提高效率,节省IO时间。指令越多效果越好。

压力测试 redis-benchmark
指令:redis-benchmark -t set -q

9.事务

为确保原子性(事务全部成功或全部失败)
指令:multi/exec/discard,watch/unwatch
Redis没有原子性,只能保证隔离性

经验:和pipeline一起使用压缩io操作

watch监控一个变量
经验:若监控变量一旦被修改那么事务就会失败

问题:为什么redis不支持回滚?
1.只检查语法错误
2.不需要支持回滚,目的是简单高效

10.小对象压缩

Redis有两种bit编译,一种是32bit,第二种是64bit。使用32bit可以少一半内存,Redis的内存使用不超过4G。

小对象压缩存储ziplist
ziplist是一个紧凑的字节数据结构,为防止对象过大,conf里的限制条件
hash-max…
list-max…
zset-max…
set-max…

内存回收机制
Redis中数据是保存在内存中的,内存是由多个页组成
1.Redis存储key是分布到各个页中
2.简单删除key是将删除,但其他key还在页中,所以内存小不了
3.执行flushdb和flushall所有key被干掉,内存释放。

内存分配算法
两种

  1. jemalloc(Redis使用,性能稍好)
  2. tcmalloc

指令:info memory

11.主从同步

CAP
C-Consistent 一致性
A-Availability 可用性
P-Partition tolerance 分区容忍性
特点:一致性和可用性两难全
通常Redis集群满足可用性,单机主从满足一致性(指令AOF)

Redis支持主从同步和从从同步
增量同步(没懂):
Redis同步的是指令流

快照同步(besave)
增加从节点
无盘复制
Wait指令

12.哨兵模型Sentinel

哨兵模型单机使用保证一致性

不能保证消息不会丢失,可以限制延迟过大

  1. min-slaves-to-write 1 至少一个从节点
  2. min-slaves-max-lag 10 10s没有收到就断开

13.Codis

是Go语言开发,使用Redis协议对外提供服务。
Codis是无状态的转发代理中间件,可动态增加Redis实例实现扩容需求

分片原理(类似hashmap)

将所有的key划分为1024个槽,先对客户端传过来的key做crc32计算hash值,再对1024取模,余数就是key对应的槽位。
当Redis扩容时,对槽位进行调整,是通过SLOTSSCAN指令遍历slot所有key,然后挨个迁移到新节点上

特点:
自动均衡:每个Redis的slots数量平衡
缺点:

  1. 不支持事务
  2. key值不宜过大
  3. 增加proxy层,性能有所下降
  4. 增加zk的代价

优点:

  1. 简单
  2. 易调试

数据同步

是通过ZooKeeper实现同步持久化槽位关系,这里可以体现ZooKeeper的数据同步功能

14.Cluster

特点:

  1. 去中心化
  2. 精细,slots为16364
  3. 定位快
  4. 官方提供

槽位定位算法

key值使用crc32算法得到hash值,再对16384取模获取具体槽位

跳转

如何找到槽位
若发到一个错误节点,这个节点将返回一个正确节点信息,再从定向到正确节点

迁移

提供redis-trib手动调整
状态为migrating(源节点)–>importing(目标节点)–>删除内容(源节点)
过程为同步,会阻塞到key被成功删除

若key数据小,migrating快,很大容易卡顿,影响集群效率

访问流程

  1. 访问若两个槽都存在部分key数据,客户端先访问旧节点,若存在旧节点里正常处理。若不存在就有两种可能,不存在或者新节点里。
  2. 旧节点不知道,会返回一个-ASK targetNodeAddr的重定向指令。
  3. 客户端收到后,先去目标节点执行一个asking指令,然后执行原先操作。(asking指令是告诉目标指令下条指令需要处理)
    结论是:影响效率,一个指令在迁移过程中需要3个ttl,正常需要一个ttl

容错

主从替换
cluster-require-full-coverage 允许部分节点故障
cluster-node-timeout 超时时进行主从切换
cluster-slave-validity-factor 超时宽松容错松弛系数,0为不抗拒网络抖动

投票机制
经过其他节点一起投票判断该节点是否下线,超过一半时就下线并主从替换

槽位感知和集群变更感知

15.Stream

5.0才出的数据结构,借鉴于kafka的设计
弥补Pub/Sub的缺点。

数据结构类似持久化得消息链表
分别是:

  1. 链表
  2. last_delivered_id(游标)
  3. 消费组
  4. 消息ID
  5. 消息内容
    Redis深度探险知识总结

消费流程

Stream 提供了 xreadgroup 指令可以进行消费组的组内消费,需要提供消费组名称、消
费者名称和起始消息 ID。它同 xread 一样,也可以阻塞等待新消息。读到新消息后,对应
的消息 ID 就会进入消费者的 PEL(正在处理的消息) 结构里,客户端处理完毕后使用 xack
指令通知服务器,本条消息已经处理完毕,该消息 ID 就会从 PEL 中移除。

特点

  • 可持久化阻塞消费。
  • 通过ack保证消息的顺序性。
  • 可以控制消息的长度 PEL:保证消息至少消费一次,不会丢失

16.Info

通过强大的 Info 指令,你可以清晰地知道 Redis 内部一系列运行参数。

九大参数

 1、Server 服务器运行的环境参数
 2、Clients 客户端相关信息
 3、Memory 服务器运行内存统计数据
 4、Persistence 持久化信息
 5、Stats 通用统计数据
 6、Replication 主从复制相关信息
 7、CPU CPU 使用情况
 8、Cluster 集群信息
 9、KeySpace 键值对统计数量信息
# eg
# 获取所有信息
> info
# 获取内存相关信息
> info memory
# 获取复制相关信息
> info replication

17. 过期策略

过期集合

redis 会将每个设置了过期时间的 key 放入到一个独立的字典中,以后会定时遍历这个
字典来删除到期的 key。

定时扫描策略

1、从过期字典中随机 20 个 key;
2、删除这 20 个 key 中已经过期的 key;
3、如果过期的 key 比率超过 1/4,那就重复步骤 1;

丛库过期策略

从库不会进行过期扫描,从库对过期的处理是被动的。主库在 key 到期时,会在 AOF
文件里增加一条 del 指令,同步到所有的从库,从库通过执行这条 del 指令来删除过期的
key。

LRU

  • noeviction 不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样
    可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。
  • volatile-lru 尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。没有设置过 期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。
  • volatile-ttl 跟上面一样,除了淘汰的策略不是 LRU,而是 key 的剩余寿命 ttl 的值,ttl 越小越优先被淘汰。
  • volatile-random 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。
  • allkeys-lru 区别于 volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不 只是过期的
    key 集合。这意味着没有设置过期时间的 key 也会被淘汰。
  • allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。
  • volatile-xxx 策略只会针对带过期时间的 key 进行淘汰,allkeys-xxx 策略会对所有的 key
    进行淘汰。如果你只是拿 Redis 做缓存,那应该使用 allkeys-xxx,客户端写缓存时 不必携带过期时间。如果你还想同时使用Redis 的持久化功能,那就使用 volatile-xxx 策略,这样可以保留没有设置过期时间的 key,它们是永久的 key 不会被LRU 算法淘 汰。

懒惰删除

在 4.0 版本引入了 unlink 指令,它能对删除操作进行懒
处理,丢给后台线程来异步回收内存。flushdb 和 flushall 指令,用来清空数据库,这也是极其缓慢的操作。

1、slave-lazy-flush 从库接受完 rdb 文件后的 flush 操作
2、lazyfree-lazy-eviction 内存达到 maxmemory 时进行淘汰
3、lazyfree-lazy-expire key 过期删除
4、lazyfree-lazy-server-del rename 指令删除 destKey

18. 安全

  1. 指令安全
  2. 端口安全
  3. Lua安全
  4. SSL 代理

本文地址:https://blog.csdn.net/qq_43168682/article/details/110353124

相关标签: redis 数据库