首页 > 数据库 >Redis

Redis

时间:2022-10-18 10:44:13浏览次数:48  
标签:主库 缓存 Redis redis 复制 从库 节点

非关系型数据库,结构上key-value存储。

redisdoc.com # 在线的命令手册

memcache,是纯内存型数据库。redis是内存+磁盘。2者全部数据都是保存在内存中。

redis3.0开始支持redis cluster ,去中心化。任意节点进行读写操作都可以。

支持持久化存储、支持事务、支持主从、支持集群

1、redis使用场景

  • 数据缓存
  • session共享(会话保持)
  • 计数器

redis+lua:lua作为封禁IP,redis作为计数。

  • 消息队列

2、redis安全机制

bind 0.0.0.0 设置允许远程登录

protected-mode yes 保护模式,yes启用

requirepass 123456 登录密码,和上面配合使用

auth 123456 # 进行认证

3、redis持久化

3.1、RDB

数据文件:rdb文件,基于快照方式实现。将内存数据原封不动保存一遍。

缺点:会丢失持久化过程中的问题。

rdb实现方式的2种方式

1)、save

立刻执行,同步,阻塞写入。

缺点:持久化时候redis服务阻塞,不能对外提供服务。最短间隔只能是1min。

2)、bgsave

异步、非阻塞。

fork+copyonwrite

优点:可以一边持久化一边读写,不影响对外服务。

fork()是操作系统的api,非redis的api。fork创建出一个子进程进行持久化rdb操作,共享父类的内存数据,仅仅是那一刻的内存数据,后期主进程修改对子进程不可见。将快照内容写入一个临时文件,写入完成将改名为dump.rdb。

参数配置

save

save 900 1
save 300 10
save 60 10000

stop-writes-on-bgsave-error

启用了rdb且最后一次后台保存数据失败,redis停止持久化操作。好处是让人发现数据没有正确持久化到磁盘上,否则不会引起注意。

rdbcompression

对于存储在磁盘中的快照,设置是否进行压缩。

rdbchecksum

在存储快照后,让redis使用CRC64算法进行数据校验,但是会增加10%的性能消耗。

3.2、AOF

aof更可靠。

appendfilename "appendonly.aof"
appendonly no  # yes为启用

优点:最大限度保证数据不丢失,可精细化到每秒。主要是记录redis的操作。

缺点:文件会变的很大。bgrewrite会重建优化aof文件,删除原先的aof文件,保证aof文件不会太大。

aof参数配置

no-appendfsync-on-rewrite

在aof或者写入rdb时候,会执行大量IO,此时对于everysec和always模式时,执行fsync会阻塞,但是最安全,不会丢失数据;否则设置为yes,此时没有进行写入磁盘操作,而是写入内存。如果redis挂掉,会丢失30s的数据。

appendfsync

写入aof的频率:always(每次操作)、everysec(每秒)、no(不主动,系统判断写入)。

auto-aof-rewrite-percentage

何时重写:aof文件大小超过上次重写大小的百分之多少进行重写。默认100,二倍。

auto-aof-rewrite-min-size

允许重写的最小aof大小。避免达到约定百分比但是寸尺很小的情况吗,还需要重写。

aof-load-truncated

aof尾部发生损坏的时候,加载文件还是报错退出。

两种持久化策略,优先加载aof,因为其更可靠。

4、redis备份

备份持久化生成的rdb文件。

关闭rdb和aof

注释3个save,新增save ""
appendonly no

拷贝rdb。

5、配置文件详解

img

6、redis数据类型

img

img

1、字符串类型

set key value [ex seconds] [NX|XX] 新增

可选参数:

  • ex seconds:过期时间 秒
  • NX 键不存在,才设置
  • XX 键已存在,才设置

append key value1 # 拼接存在的value

set name rose

append name 22

get name =>rose22

INCR num 自增+1

decr 自减-1

incrby key 20 自增+20

set age 2

INCR age => age => 3

mset key1 value1 key2 value2... 批量设置

mget key1 key2... 批量获取

strlen key 获取字符个数

type key 查看类型

2、哈希表类型 hash

hset key field value //新增 hset userinfo name jack

hget key field // 查询一个

hgetall key // 查询全部

hmset\hmget 批量新增和查询

3、列表类型 list

双向列表,可以实现消息队列的功能。利用push存入list,pop从列表中取出。

rpush  key  value  # 定值推到列表右侧
lpush  key  value  # 定值推到列表左侧
rpop  key  # 列表右端弹出值
lpop  key  # 列表左端弹出值
lrange start stop  # 取范围值,-1 最后一位  # lrange 0 -1
lindex  key  index  # 下标取值,0开始
lrem  list1  -2  "tom"  # 从尾部移除2个tom    0为移除全部

4、无序集合set

集合成员不可重复且无序的;集合是通过hash table实现的,添加、删除、查找复杂度都是O(1)`

img

5、zset

7、redis主从复制

redis提供主从复制模式,保证多台服务器数据一致性,且主从 服务器之间采用读写分离的方式。

主服务器可以进行【读写】操作,而从服务器一般是只读(slave-read-only来控制),并接受主服务器的【数据同步】。且数据复制是单向的。

img

一个主服务器可以有多个从服务器,一个从服务器只能有一个主服务器,不支持主主复制。从服务器可以作为主服务器,下分组成从服务器。

img

复制方式

  • 全量复制:第一次同步时
  • 增量复制:只会把主从库网络断开期间主库收到的命令,同步给从库

2.8版本之前只有全量复制,只会才有增量复制。

全量复制

1、确定主从关系

replicaof host port (5.0之前使用salveof)命令让一个redis服务成为另一个redis服务的从库。

replicaof 192.168.1.1 6379

2、全量复制的流程

img1)、从库向主库发送psync ? -1命令,主动请求进行完整同步

这一步是主从库间建立连接、协商同步的过程,主要为全量复制做准备。这一步,从库和主库建立起连接,并告诉主库即将进行同步,主库确认回复后,主从库就开始同步。

从库给主库发送psync命令,表示要进行数据同步,主库根据这条命令启动复制。psync包含主库的runID和复制进度offset两个参数。

runID是redis启动时给每个实例创建的唯一ID,标识不同的redis实例,当从库和主库第一次复制时,不知道主库的runID,所以将runID设置为?,offset表示复制进度,主要为了增量复制服务,这里因为是全量复制,所以是-1。

2)、主库向从库发送FULLRESYNCm命令并带上2个参数,主库的runID和复制进度offset。

3)、主库执行bgsave命令,生成RDB文件,发送给从库。

从库接收到RDB文件,会先清空数据库,然后加载RDB文件。因为从库通过replicaof命令开始和主库同步前,可能保存了其他数据,避免影响,会先清空数据库。

4)、将发送过程中收到的指令存储到replication buffer中,发送给从库。

从库接收并载入rdb文件时,主库仍然在写入数据,主库准备了个缓存区,数据写入缓存区,从库载入完成,缓存区的数据推送过去。

如果主从库断线,就会进行重新复制,每次都需要生成RDB文件并传输,费时耗资源,产生了增量复制。

增量复制

img

1、复制偏移量 replication offset

主服务和从服务器会分别维护一个复制偏移量,如果主从库复制偏移量相同,二者状态一致,如果偏移量不同,就说明是二者数据库状态不一致,从库缺少数据,需要使用增量复制来同步。

2、复制积压缓冲区 replication backlog

主库的写命令,除了传给从库后,还会写入replication backlog,这是一个固定长度的先进先出FIFO的队列,默认大小为1MB,其在内存是一个环形结构。

img

主库按照顺时针方向写入命令,主库最新写入位置即为上文提到的主库偏移量,这里的master offset,假设从库在set key2 2 后断开连接,也就是slave offset位置,当他重连时,再次给主库发送psync指令时,会带上offset。根据上下文,主库发现从库偏移量和主库不一致,需要进行增量备份,此时主库会计算出master offset和salve offset之间的指令,并发送给为该从库准备的replication buffer里,进而发送给从库,从库进行写入后便又恢复和主库一致的状态。

img3、断开重连

断开重连不一定是增量复制。

  • 整个replication backlog是个环形结构,也就是说最新的命令会将老的命令覆盖,断开时间太久,就只能进行全量复制了,所以可以将replication buffer配置尽量大一点。
  • 每个值都有自己的runID,这个值在服务启动的时候自动生成,由40个随机16位字符组成,从库断开连接时,会将主库的runID一起发送过去,主库会判断runID是否为自己,就会告知进行全量复制。

8、哨兵

主要功能包括主节点存活检测、主从运行情况检测、自动故障转移、主从切换。redis sentinel最小配置是一主一从。他也是一台redis服务器,不对外提供服务,一般配置为单数。

Sentinel执行以下4个任务:

  • 监控:不断检查主服务器和从服务器是否运行。
  • 通知:哨兵检查服务器出现问题,就会通知其他哨兵。
  • 自动故障转移:当主节点不能正常工作,Sentinel或开始一次主动的故障转移操作,将与失效主节点是主从关系的其中一个节点升级为新的主节点,并将其他从节点指向新的主节点,避免人工干预。
  • 配置提供者:客户端应用在初始化时连接的是Sentinel节点集合,从中获取主节点信息。

监控的工作流程

①哨兵发送 info 指令,并且保存所有哨兵状态、主节点和从节点的信息。

②主节点会记录 redis 实例的信息,主节点记录的信息跟哨兵记录的信息看起来是一样的,实际上还是有点区别。

③哨兵会根据在主节点拿到的从节点信息,给对应的从节点也发送 info 指令。

④接着哨兵 2 来了,同样的也会给主节点发送 info 指令,并且建立 cmd 连接。

⑤这个时候哨兵 2 也会保存跟哨兵 1 一样的信息,只不过是保存的哨兵信息是 2 个。

⑥这个时候为了每个哨兵的信息都一致它们之间建立了一个发布订阅。为了哨兵之间的信息长期对称它们之间也会互发 ping 命令。

⑦当再来一个哨兵 3 时,也会做同样的事情,给主节点和从节点发送 info。并且跟哨兵 1 和哨兵 2 建立连接。

通知的工作流程

sentinel 会给主从的所有节点发送命令获取其状态,并且会把信息发布到哨兵的订阅里。

故障转移原理

哨兵会一直给主节点发送 publish sentinel:hello,直到哨兵报出 sdown。哨兵还会往内网里发布消息说明这个主节点挂了。其余的哨兵也会发送信息确认主节点是否真的挂了。都认为挂了,就会修改状态为odown。这时候哨兵们就会竞选谁去负责推选新节点。推选出来了就会断开原主节点,且其他节点连接新节点。

推选新主节点规则:

  • 去掉不在线的
  • 去掉响应慢的
  • 与原主节点断开时间最久的干掉
  • 根据优先级
  • 判断offset偏移量,判断数据同步性
  • 判断runid,时间早的上位

sdown和odown 主观宕机、客观宕机

quorum和majority

quorum:确认odown的最少的哨兵数量

majority:授权进行主从切换的最少的哨兵数量

哨兵的原理

  • 第一个定时任务:每个Sentinel每隔1秒向master、slave以及其他sentinel发送ping命令。作用:作为心跳检测。
  • 第二个定时任务:每个Sentinel每隔2秒向master的一个channel发送自己掌握的集群信息和自己的信息,利用redis的发布订阅功能,每个sentinel节点都会订阅这个channel,每个sentinel都会知道别的sentinel掌握的集群信息。作用是用于信息交换,了解别的sentinel信息和他们对于主节点的判断。
  • 第三个定时任务:每隔10秒都会想master和slave发送INFO信息。作用:掌握最新的集群拓扑结构。

集群脑裂

就是一个集群中出现2个master情况。

如何发生的:当集群中的master网络出现问题,和集群中的slave和sentinel通信出现问题,但是本身没有挂。这个时候sentinel连不上master,选择一个slave变成master,这个时候client还没有来得及切换,就会把数据写入原来的master中,一旦网络恢复,原来的master就会变成slave,从新的master上复制数据,那么client写入旧的master的数据就会丢失。

如何解决:配置项min-slavers-to-write 1和min-slavers-max-lag 10。这2个配置项组合在一起就是至少有一个slave和master数据同步延迟不超过10秒,如果所有slave都超过10秒了,那么master就会拒绝接收请求。如果发生脑裂,如果client向旧master写入数据,旧的master不能向别的slave同步数据,所以client最多只能写入10秒的数据。如果出现旧的master和slave都和sentinel无法通信了,就可以调整min-slaver-to-write的大小。

缓存穿透

就是查询不到数据。用户查询数据,发现redis内存数据库中没有,就会向持久化层的数据库查询,发现也没有,于是本次查询失败,当用户很多的时候,缓存没有命中,于是都去请求了持久层数据库,给持久层数据库造成很大压力,出现缓存穿透。

解决方案:

布隆过滤器:是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的压力。

缓存空对象:就是当一个请求过来,缓存中和数据库都不存在,第一次请求会跳过缓存,进入数据库查询,并且访问数据库后返回空,此时将空值也进行缓存。

缓存击穿

就是一个key很热门,在不停的扛住大并发,大并发集中对一个点进行访问,当这个key失效的瞬间,持续的大并发穿破缓存,直接到达持久化数据库,对数据库的访问压力瞬间增大。

解决方案:

  • 设置热点数据永不过期
  • 加互斥锁。在用于进行大并发访问的时候,在查询缓存和数据库的过程中加锁,只能第一个进来的请求进行执行,当第一个请求把数据放进缓存中,接下来的访问就会访问缓存,防止缓存击穿。

缓存雪崩

指在一瞬间,缓存集中过期失效,无数请求绕过缓存,直接请求数据库。

造成原因

  • redis宕机
  • 大部分数据失效

解决方案:

  • 搭建高可用集群
  • 设置不同的过期时间,防止同一时间内大量key失效。

标签:主库,缓存,Redis,redis,复制,从库,节点
From: https://www.cnblogs.com/20190707wdd/p/16801815.html

相关文章

  • Redis Zset的实现为什么用跳表,而不用平衡树?
    之前写过一篇Redis数据类型的底层数据结构的实现,其中提到,ZSet对象的底层数据结构实现之一是跳表。然后,有读者就问:为什么不使用平衡树(如红黑树、AVL树)?我们先来了解下......
  • goRedis
    goRedis简介实现redis操作使用gogetgithub.com/wms3001/goRedis实例连接goRedis:=GoRedis{}goRedis.Db=10goRedis.Addr="192.168.4.81:6379"goRedis.Password="gl......
  • redis配置
    redis配置1.使redis后台运行1)编辑redis.conf文件2)在vim编辑器输入/dae查找到daemonize将值改为yes2.设置密码1)编辑redis.conf文件2)在vim编辑器输入/requirepass查......
  • Redis6.2集群部署
    复制集群概述&.集群特点(1)读写分离:Redis复制集群采用主写从读机制进行读写分离,易于性能扩展.(2)数据容灾:Redis复制集群仅支持一主多从,且从服务器也可以关联从服......
  • Redis6.2安装配置
    安装教程[概述]Redis使用标准版本标记进行版本控制,奇数版本为发行版,偶数版本为稳定版&.容器安装Redis镜像拉取:默认从DockerHub拉取镜像,嫌慢可使用阿里镜像仓库.......
  • Redis6.2基础概述
    Redis密码管理:所有库使用同一个密码进行统一管理.库的操作......
  • 为什么用 Redis 作为 MySQL 的缓存?
    主要是因为 Redis具备「高性能」和「高并发」两种特性。1、Redis具备高性能假如用户第一次访问MySQL中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用......
  • Redis 数据类型以及使用场景分别是什么?
    Redis提供了丰富的数据类型,常见的有五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)。随着Redis版本的更新,后面又支持了四种数据类型: BitMap(2.2版......
  • Redis是什么
    Redis(RemoteDictionaryServer),即远程字典服务。Redis是一种基于内存的数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场......
  • Nodejs+Redis实现简易消息队列
    前言消息队列是存储数据的一个中间件,可以理解为一个容器。生产者生产消息投递到队列中,消费者可以拉取消息进行消费,如果消费者目前没有消费的打算,则消息队列会保留消息,直......