resdis
2021-05-29 13:29:34 8 举报
AI智能生成
redis总结。 可参考 黑马公开课 后续补齐redis的实现原理
作者其他创作
大纲/内容
redis
主从复制
三高架构
高并发
高性能
高可用
为避免单机故障与容量瓶颈,将多台服务器链接在一起提供服务还可提供冗余备份,提高可靠性
保证数据同步/一致性问题
单位时间内能尽可能长时间的提供服务
redis单机的高可用限制
单机故障
硬盘/系统崩溃
数据丢失
容量瓶颈
内存不足
职责分类
master
写数据
写操作,自动同步到slave端
读数据(可忽略)
slaver
读数据
写(禁止)
核心问题:数据同步—master数据复制到slave中
主从复制的好处
读写分离:提高服务器的读写负载能力
负载均衡:多个从节点分担数据读取负载,大大提高Redis服务器并发量与数据吞吐量
故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复
数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式
高可用基石: 基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案
主从复制流程
建立连接
数据同步
全量复制是一个RDB过程,部分复制时一个AOF过程
runid
服务器运行ID是每一台服务器每次运行的身份识别码,由40个随机字符组成
服务器之间传递,必须每次操作携带对应的运行id,用于对方识别
复制积压缓冲区
对master来说每个slave对应一个复制缓冲区,一个FIFO的队列
保存master收到的所有指令(仅影响数据变更的指令,例如set, select)
master收到数据修改的指令,通过aof的方式刷写到slave中,复制缓冲区就作为aof的缓存
offest
用于标志slave与master之间数据的差异
命令传播
心跳机制:master与slave间需要进行信息交换,实现双方连接保持在线
当slave多数掉线,或延迟过高时, master为保障数据稳定性,将拒绝所有信息同步操作
min-slaves-to-write 2min-slaves-max-lag 8
slave数量少于2个所有slave的延迟都大于等于8秒时强制关闭master写功能,停止数据同步
master心跳
PING,周期一般10s(需要维护多个slave),由repl-ping-period决定
判断slave是否在线
可通过info replication查询slave最后一次连接时间间隔,lag为0/1正常
slave心跳
REPLCONF ACK {offset},1s,汇报自己的偏移量,以获取最新数据
判断master是否在线
基于心跳机制的命令传播
常见问题
频繁全量复制
master重启导致的全量复制
重启前,master通过RDB进行offest与runid的持久化
网络不佳导致的复制缓冲区溢出
修改复制缓冲区的大小repl-backlog-size
1. 测算从master到slave的重连平均时长second2. 获取master平均每秒产生写命令数据总量write_size_per_second3. 最优复制缓冲区空间 = 2 * second * write_size_per_second
频繁网络中断
slave频繁断开,master的cpu占用过高
slave与master断开
master的平频率过低
子主题
slave间数据不一致
监控主从节点延迟(通过offset)判断,如果slave延迟过大,暂时屏蔽程序对该slave的数据访问
slave-serve-stale-data yes|no
优化主从间的网络环境,通常放置在同一个机房部署,如使用阿里云等云服务器时要注意此现象
哨兵模式
简介
哨兵(sentinel) 是一个分布式系统,用于对主从结构中的每台服务器进行监控,当master出现故障时通过投票机制选择新的master并将所有slave连接到新的master
哨兵作用—主从切换
哨兵也是一台redis服务器,只是不提供数据服务,通常哨兵配置数量为单数(便于投票)
流程
监控
监控master与slave是否正常运行master存活检测,m,s运行状况检测
sentinel首先通过info指令建立cmd连接获取master中信息(master,slave list,sentinel list)
通过sentinel list建立publish subscribe连接哨兵,对方添加sentinel list
通过 slave list建立cmd连接,获取slave的详细值(runid/offset/masterhost...)
数据获取流程
通知
当被监控的服务器出现问题时, 向其他(哨兵间,客户端) 发送通知。
任何哨兵都与主从连接。此时哨兵会定时询问查询主从的连接状态。但任一哨兵获得连接状态,便在哨兵内传输
自动故障转移
断开master与slave连接,选取一个slave作为master,将其他slave连接到新的master,并告知客户端新的服务器地址
标记下线
sentinel询问master,如无响应则反复询问,后主观标记其下线
该sentinel将故障信息传递给其余哨兵,其余哨兵对其询问(若是哨兵故障标记主机下线,则无法在哨兵间泛洪)
哨兵中超过半数认为master挂机,则标记为客观下线。标记完成
选取主sentinel用于处理master下线
所有哨兵参与竞选广播自己的信息,每轮竞选次数 + 1;
重新连接
重新选择master原则
1 在线
2 响应快
3 与原master断开时间短
4 优先原则
优先级高
runid小
确定为master:向新的master发送slaveof no one
连接新master:向其他slave发送slaveof 新masterIP端口
失效master重新恢复?
作为slave加入
集群
使用网络将若干台计算机联通起来,并提供统一的管理方式,使其对外呈现单机的服务效果
分散单台服务器的访问压力,实现负载均衡
分散单台服务器的存储压力,实现可扩展性
降低单台服务器宕机带来的业务灾难
原理
将所有的存储空间计划切割成16384份(非每个key),每台主机保存一部分
各个服务器将相互通信,保存各自槽的编号范围
放置时:计算出key应该保存的位置
1 CRC16循环冗余检测,获得一个类hash值
取模hash % 16384,获得槽位
获取时:一次命中返回,未命中,告知具体位置
增减节点(服务器)如何处理 — 一致性hash
存在倾斜问题,如BC失效,则D要负责BCD的任务
引入虚拟节点。一个物理节点映射多个虚拟节点缓解问题
一致性hash图解
服务器在一个环中,若hash命中则由其负责,若未命中则顺时针下一个负责
若某个节点失效(B),则顺延到下一个负责(C)
redis崩溃预防
缓存预热
服务器启动后迅速宕机
请求数高
主从将同步频率高,吞吐量大
解决方案
缓存预热就是系统启动前, 提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!
缓存雪崩
缓存雪崩就是瞬间 过期 数据量太大,导致对数据库服务器造成压力。如能够有效避免过期时间集中,可以有效解决雪崩现象的出现(约40%),配合其他策略一起使用,并监控服务器的运行数据,根据运行记录做快速调整。
方案
限制上游流量
js过滤,页面静态化处理 + 消息队列
多级缓存
nginx + redis + ehcache
性能监控机制
redis的努力
LRU与LFU切换使用
分期过期 + (固定过期 + 随机值),稀释集中过期key数量
超热数据永久化
缓存击穿
缓存击穿就是单个高热数据过期的瞬间,数据访问量较大,未命中redis后,发起了大量对同一数据的数据库访问,导致对数据库服务器造成压力。
提前设定,例如电商销量等
redis监控,现场调整key过期时间
添加二级缓存(防key过期后,对单key的大量访问)
缓存穿透
缓存击穿访问了不存在的数据,跳过了合法数据的redis数据缓存阶段,每次访问数据库,导致对数据库服务器造成压力。
策略
缓存key
白名单策略
布隆过滤器
布隆过滤器是一个二进制数组
首先对数组进行添加,经过不同的hash算法,分布到二进制数组中,设置为1
判断一个数是否存在,即经历所有的hash算法,若获得的所有数字都为1则认为该数字存在
bitmap
本质和hashset差不多,判断一个数是否已经存在,但占用体积小
布隆存在问题,返回结果不一定准确,由一定误差
hash算法的个数
二进制数组的长度
存入布隆的个数
由三者决定了误差大小
布隆过滤器参数设置。
可调用com.google.gruve直接调用api
监控命中率与null占比
key加密
性能监控
什么是redis
抢购/秒杀服务崩溃
原因
海量用户
本质
关系型数据库的奔溃MySQL
使用NoSQL
减少IO——内存存储
不储存数据关系,仅储存数据
性能瓶颈:磁盘IO
扩展瓶颈:数据关系复杂,可扩展性差
解决思路
NoSQL
含义
No-Only-SQL,作为关系型数据库的补充
特征
可扩容,可伸缩
大数据量下高性能
灵活的数据模型
常见NoSQL
Redis memcache HBase MongoDB
基本操作
功能性命令
清屏
clear
帮助
help @ + tab 按群组查询
help command
退出
exit
quit
数据间没有必然的关联关系
内部采用单线程机制进行工作
持久化支持。可以进行数据灾难恢复
单线程操作为何能够高性能那?
内存操作,而MySQL是在磁盘中进行
只存储数据,不存储关系
常用数据结构
什么叫redis内数据结构
redis 自身是一个 Map,其中所有的数据都是采用 key : value 的形式存储
数据类型指的是存储的数据的类型,也就是 value 部分的类型, key 部分永远都是字符串
string
区别在于 json便于存储,但是修改复杂
储存内容
通常使用字符串
set age 25 EX 10
带超时的设置
setex age 10 30
设置过期为10s
mset age 25 EX 20 name wangkang
带超时的多个设置
increby age 10incre ageincrebyfloat age 1.5
decrby age 10decr age
区别:mset减少客户到到服务器多次的往返时间
对数值的一个操作,可用来保证MySQL分库分表时的主键唯一性
单线程操作,无需考虑并发影响主键
规范性使用使用方式表名:主键名:主键值:字段
set user:id:25506:fans 35533set user:id:25506:blog 323set user:id:25506:follow 68
hash
储存模型
可用来对string 储存的json数据进行优化
hset user:id:23 blogs 324hgethgetallhdel
hmset user:id:23 fans 233 blogs 32hmget
hincrby key filed valuehdecrby key filed value
hlenhexists key filedhkeyshvals
应用场景
set
储存模型—hash的屏蔽
将hash的value屏蔽
一度关联/二度关联/深度关联
一度关联
显示共同关注
共同好友
从A获得其好友B的好友列表
二度关联
从A出发,获得其好友B的购物清单
从A出发,获得其好友B的游戏充值记录
深度关联
sadd users wangk tangxsmembers userssrem users tangx
scard users 获得总数sismember users tangx
随机获取
srandmember users 3 users中随机获取3个值
spop users 3随机去除3个值。
应用:随机推荐
交并差
注意差集
sinter users fanssunion users fanssdiff users fans
数据储存转移
sinterstore inter users fanssunionstore union users fanssdiffstore diff users fans
可用来做简单的角色权限合并校验
做权限校验时,是使用sismember还是smermember将数据返回那?
应当将数据返回,返回后在业务层对数据校验!这样数据与业务分离,耦合度降低!
数据转移
smove union diff wangk 将wangk数据从union转移到diff
访问统计
权限控制
校色权限认证
黑白名单
基于经营战略设定问题用户发现、鉴别规则 周期性更新满足规则的用户黑名单,加入set集合 用户行为信息达到后与黑名单进行比对,确认行为去向 黑名单过滤IP地址:应用于开放游客访问权限的信息源 黑名单过滤设备信息:应用于限定访问设备的信息源 黑名单过滤用户:应用于基于访问权限的信息源
sort_set
储存模型—set的魔改
多一列score
score并不是用于存储数据,只是用来排序使用
按score范围
zrangebyscore key min max [WITHSCORES] [LIMIT]zrevrangebyscore key max min [WITHSCORES]zremrangebyrank key start stopzremrangebyscore key min max
榜单排名
带有权重的任务队列
对于带有权重的任务,优先处理权重高的任务,采用score记录权重即可
多条件任务权重设定如果权重条件过多时,需要对排序score值进行处理,保障score值能够兼容2条件或者多条件.例如外贸订单优先于国内订单,总裁订单优先于员工订单,经理订单优先于员工订单 因score长度受限,需要对数据进行截断处理,尤其是时间设置为小时或分钟级即可(折算后) 先设定订单类别,后设定订单发起角色类别,整体score长度必须是统一的,不足位补0。第一排序规则首位不得是0
注意组合权重时,需要保证多条件的数据对其,补0操作
限时服务
对于基于时间线限定的任务处理,将处理时间记录为score值,利用排序功能区分处理的先后顺序 记录下一个要处理的时间,当到期后处理对应任务,移除redis中的记录,并记录下一个要处理的时间 当新任务加入时,判定并更新当前下一个要处理的任务时间 为提升sorted_set的性能,通常将任务根据特征存储成若干个sorted_set。例如1小时内, 1天内,周内,月内,季内,年度等,操作时逐级提升,将即将操作的若干个任务纳入到1小时内处理的队列中
分段处理
list
存储模型
底层采用双向链表,维护一个头指针与尾指针
强调顺序,可左右取值与添加
哪边是头,哪边是尾巴?
一般选取左进右出
添加
获取
删除
带时限的删除
使用场景
点赞列表维护/关注列表维护
新闻列表按时间维护
特殊数据结构
与常用数据结构的区别
HyperLogLog
GEO
通用操作
keys
配置文件
关于服务器
daemonize yes|no 守护线程
bind 127.0.0.1 绑定主机地址
port 6379 绑定端口号
databases 16 数据库数量
关于日志配置
loglevel debug|verbose|notice|warning
日志级别开发期设置为verbose即可,生产环境中配置为notice,简化日志输出量,降低写日志IO的频度
logfile 端口号.log 日志文件名
关于客户端配置
maxclients 0 (默认无限制)同一时间客户端链接上限。超过server关闭新连接
timeout 300 客户端闲置等待最大时长,达到最大值后关闭连接。
持久化
什么是持久化
利用磁盘永久存储数据,在特定时间恢复
防止数据意外丢失。
持久化分类
快照存储RDB
逻辑存储AOF
RDB
常用指令
两者区别
save
阻塞redis线程
bgsave
后台开启子线程,异步存储
配置启动
redis-server conf/reids-6973.conf
常用配置
dbfilename dump.rdb
dir location
save second changes
配置保存设置(bgsave)
rdbcompression yes
开启数据压缩(默认yes)
rdbchecksum yes
数据校验(开启损失性能)
stop-writes-on-bgsave-error yes
储存中error,停止保存
优劣
优点
快照,全量复制
恢复数据快
缺点
无法实时持久化IO性能低,数据丢失可能性大
每次bgsave启动子线程,牺牲性能
各版本不兼容现象
AOF
逻辑存储,记录数据更改的指令
写数据的策略
always
数据零误差,性能低,不建议
everysec
数据准确性较高, 性能较高,建议使用,也是默认配置
no
操作系统控制AOF周期
整体不可控
数据重写
相对于RDB有数据压缩,AOF采取数据重写的方式减少储存量
降低磁盘占用
提高持久化效率,提高IO性能
提高数据恢复的速度
重写规则
对已超时的数据不在写入文件
忽略无效指令
增改没有的数据
多次对同一数据修改,只保留最后一条指令
对同一key的多个命令,合并为一个(mult)
重写方式
手动重写bgrewriteaof
配置自动重写
对比参数可通过 info指令查询,aof_current_size为缓存中数据大小aof_base_size为基础大小,默认系统指定
重写流程
配置参数
自动重写触发条件
appendonly yes
开启aof
appendfsync everysec|no|always
写数据策略
dbfilename dump-6793.aof
auto-aof-rewrite-percentage percentage 30
auto-aof-rewrite-min-size size 64mb
RDB与AOF区别
如何选择
对数据非常敏感
AOF -存储策略可设置为everysec,保证性能的同时,保证数据最多丢失1s,恢复速度慢
数据阶段有效性
保证阶段内有效/容忍数分钟的数据丢失,恢复速度快。性能可能低。
灾难恢复
双保险策略
同时开启,重启后redis优先采取aof恢复,降低丢失
事务
防止被其他指令打断/干扰
事务实现
工作流程
维护一个队列,但exec提交后同一执行
出现错误
语法错误
销毁队列
逻辑错误
正确的执行,错误的跳过,无回滚
常用解决办法(手动回滚)
记录修改之前的状态缓存下来
出现错误,单数据set回去,多数据克隆回去。
multi
开启事务,创建队列
exec
提交事务,执行队列
discard
锁
监控锁
watch key
监控到key发生变化,本线程终止事务执行
但多个client操作共享变量时,都首先获得 lock,再开启事务。但事务完成,修改lock,其余client便事务失败。
分布式锁
监控锁只能用作监控,而无法控制其余线程修改共享变量(共享),分布式锁解决
setnx lock-name value
获得锁后便可以操作,其余线程无法获得lock-name。事务完成后 del lock-name即可
需要规定多个线程都申请同一把锁才可生效
存在问题:不释放锁,如宕机
设定锁超时
expire lock-key second
pexpire lock-key milliseconds
超时时长设定—由业务测试后决定
测试百万次最长执行时间对应命令的最大耗时,测试百万次网络延迟平均耗时
锁时间设定推荐:最大耗时*120%+平均网络延迟*110%
业务最大耗时<<网络平均延迟,通常为2个数量级,取其中单个耗时较长即可
删除策略
数据过期
设置数据的有效期
expire key value 倒计时秒pexpire key value 倒计时秒
expireat key timestamp 倒计时时间戳pexpireat key timestamp精确到毫秒
内存模型
查看有效期
ttl key
正数-剩余销毁时间
-1 永久有效
-2 已过期/删除/未定义数据
数据删除策略
目标:平衡内存占用与CPU的占用
定时
设置定时器到达过期时间则删除。
节约内存,占用cpu性能。时间换空间
适用于cpu更强的
懒惰
内部调用expireIfNeed()函数数据过期,不做处理。
访问:未过期则返回 过期删除数据
适用于cpu弱,内存大
定期
特点
随机抽查,重点抽查
cpu检测频率可自行设置,内存压力也不大
Redis启动,读取配置hz(10),每秒钟执行hz次serverCron库的轮询
配置文件 hz =10
info (server)查询hz值
cerverCron->databasesCron单个库轮询->activeExpireCyde()库内随机抽查
随机检测W个key,key超时则删除
W由配置文件中ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP确定
每轮删除key> W*0.25则循环本数据库
小于则跳到下一个库
由参数current_db记录轮询位置
逐出算法(GC)
redis执行命令前,都会调用freeMemoryIfNeeded()检测是否充足
若内存不足则执行逐出算法
否则,OOM
8种删除策略
检测易失数据(可能过期的数据集server.db[i].expires)
volatile-lru:挑选最近最少使用的数据淘汰
实现算法双向链表 + map
get获取:从map查找,有则从链表中删除,插入到头部
put放置:从map查找,有则从链表中删除,插入到头部map中没有,则查看缓存容量。若超出,删除尾部Node。插入到头部
内部属性与构造器
get方法
put方法
volatile-lfu:挑选最近使用次数最少的数据淘汰
volatile-ttl:挑选将要过期的数据淘汰
volatile-random:任意选择数据淘汰
检测全库数据
allkeys-lru:挑选最近最少使用的数据淘汰
allkeys-lfu:挑选最近使用次数最少的数据淘汰
allkeys-random:任意选择数据淘汰
放弃数据驱逐
no-enviction(驱逐):禁止驱逐数据( redis4.0中默认策略),会引发错误OOM( Out Of Memory)
maxmemory 最大可用内存
maxmemory-samples 每次选取待删除的个数
maxmemory-policy 删除策略
0 条评论
回复 删除
下一页