缓存数据库之Redis(6.x)

本文详细介绍了Redis的数据类型、常用指令,包括String、List、Set、SortedSet和Hash,并讨论了缓存一致性问题如击穿、穿透和雪崩,以及Redis的持久化策略、内存淘汰和高可用架构,如主从复制、哨兵模式和集群模式。
摘要由CSDN通过智能技术生成

1、redis的介绍及使用场景

1.1 介绍

⼀个开源的使⽤ ANSI C 语⾔编写、遵守 BSD 协议、⽀持⽹络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库,并提供多种语⾔的 API。并且支持多种数据类型,例如string、list、set、sortset、

1.2 官网

https://redis.io/

2、redis支持的数据类型及常见的指令

2.1 通用指令

// 判断key是否存在
exist -> exist key
// 删除key
del -> del key

// 判断key的类型
type -> type key

// 查看key的存活时间
ttl -> ttl key

// 修改key的名称
rename -> rename oldName newName

2.2 数据结构之String(字符串)

2.2.1 应用场景

验证码、计数器、订单重复提交、用户登录信息等

2.2.2 常用命令

set|mset|get|mget|incr|decr|del|setex|setnx

// 设置给定key的值
set -> set key value

// 批量给定key的值
mset -> mset key1 value1 key2 value2

// 获取给定key的值
get -> get key

// 批量获取key的值
mget -> mget key1 key2 key2

// 给定key的值得加1 并且返回新的值
incr -> incr key

// 给定可以的值得增加特定的值,如果可以不存在操作之前key就会被设置为0,在进行增加
incrby -> incrby key amount

// 给定key的值得减1 并且返回新的值
decr -> decr key

// 给定key的值得减少特定的值,如果可以不存在操作之前key就会被设置为0,在进行减
decrby -> decrby key amount

// 给特定的可以设置value及过期时间
setex -> setex key seconds value

// 如果key不存在给key设定值,并返回1,如果不存在返回0
setnx -> setnx key value

*注意:
	1)给定value的值得不可以超过512MB
	2)key命名规范,不要过长,尽量用对应符号分割例如冒号,业务名:id

2.3 数据结构之List(列表)

2.3.1 数据结构介绍

list为双向链表,插入和删除时间复杂度为O(1)快,查询为O(n)慢。

2.3.2 应用场景

简单队列,列表、定时计算绑定等

2.3.3 常用命令

lpush|rpop|llen|lindex|lrange|rpush|lpop|brpop|lrem

// 给列表头部添加元素
lpush -> lpush key element

// 给列表尾部添加元素
rpush -> rpush key element

// 移除列表第一个元素并返回元素
lpop -> lpop key

// 移除列表最后一个元素并返回元素
rpop -> rpop key

// 查询列表长度
llen -> llen key

// 通过索引获取列表中的元素
lindex -> lindex key

// 获取可以对应列表的指定下标范围的元素,0表示第一个元素,1表示第二个元素,-1表示获取所有元素(lrange key 0 -1)
lrange -> lrange key 0 2

// 移除列表中最后一个元素,如果元素不存在则阻塞元素直到列表存在元素并且弹出为止(timeout 秒值)
brpop -> brpop key1 key2 ... timeout

// 移除列表中指定元素 可以指定元素的个数(count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT )
lrem -> lrem key count value

*注意:
	1)存储的都是string类型
	2)列表最多可以包含2的32-1次方个元素

2.4 数据结构之set

2.4.1 介绍

将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略,无序集合且集合元素唯一不可重复

2.4.2 应用场景

大数据里面的用户画像的标签集合,共同好友(利用交集,并集,差集)

2.4.3 常用命令

sadd|scard|sdiff|sinter|sismember|srem|sunion|smembers

// 将一个或者多个成员元素添加到指定key的集合中
sadd -> sadd key member1 member2 ...

// 返回结合中元素的数量
scard -> scard key

// 返回指定集合元素中的差集(diff - different 不相同)
sdiff -> sdiff key

// 返回指定集合元素中的交集
sinter -> sinter key

// 返回指定集合元素中的并集
sunion -> sunion key1 key2

// 判断元素是否是指定结合中的元素(存在返回1,不存在返回0)
sismember -> sismember key member

// 返回指定集合内的所有元素
smembers -> smembers key

// 移除指定集合中的指定的元素
srem -> srem key member

*注意:集合是通过哈希表实现的

2.5 数据结构之sortedset

2.5.1 介绍

使用hashmap+跳跃表skipList保证数据存储和有序。用于将一个或多个元素加入到有序的集合当中,如果成员已经是有序的成员,那么更新这个成员的分数值(score),分数可以是整数或者浮点数,有序集合可以看做是在set集合的基础上为集合中的每个元素维护了一个顺序值score,它允许集合内的元素按照score进行排序。

2.5.2 应用场景

商品热销榜单,积分应用榜单等

2.5.3 常用命令

zadd|zcard|zcount|zincrby|zrange|zrevrange|zrevrank|zrank|zrem|zscore

// 向有序集合添加一个或者多个成员,或者更新已经存在成员的分数
zadd -> zadd key score1 member1 score2 member2

// 获取指定有序集合内的元素数量
zcard -> zcard key

// 用于计算指定集合内指定分数区间的成员数量
zcount -> zcount key minScore maxScore

// 向有序集合内指定成员增加分数
zincrby -> zincrby key incrrment member

// 通过索引区间返回有序集合成指定区间内的成员(从小到大),下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。
你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。

zrange -> zrange key start stop [withscores]

// 与上面基本相同顺序为从大到小
zrevrange -> zrevrange key start stop withscores

// 返回指定集合成员的member排名,其中有序集合成员按照score值递减(从小到大)顺序排列返回对应的索引值(从0开始)
zrank -> zrank key member

// 与zrank相同 排列顺序为从大到小
zrevrank -> zrevrank key member

// 移除集合元素内的一个成员或多个成员
zrem -> zrem key member1 member2 ...

// 返回集合内指定成员元素的分值
zscore -> zscore key member

2.6 数据结构之Hash(k-v)

2.6.1 介绍

是一个string类型的field和value的映射表,hash特别适合用于存储画像

2.6.2 应用场景

购物车存储,用户对象

2.6.3 常用命令

hset|hget|hgetall|hdel|hexists|hincrby|hmset|hmget

// 设置指定key的集合中指定的字段的值
hset -> hset key field value

// 获取指定key的field元素
hget -> hget key field

// 获取指定key的全部元素
hgetall -> hgetall key

// 从key指定的集合中移除指定的的元素
hdel -> hdel key field

// 返回集合中field是否存在 存在返回1不存在返回0
hexists -> hexists key field

// 增加key指定的哈希集钟指定字段的数据,如果是-1,则是递减
hincrby -> hincrby key field increment

// 批量设置key中多个field的值得
hmset -> hmset key field1 value1 field2 value2

// 批量获取指定key内多个field的值
hmget -> hmget key field1 field2

3、缓存击穿,穿透,雪崩及常见解决方案

3.1 击穿

3.1.1 介绍

缓存内没有,但数据库中有数据的情况为击穿

3.1.2 预防

* 如果是热点数据设置热点数据不过期
* 定时更新缓存	

3.2 穿透

3.2.1 介绍

缓存内没有、数据库内也没有

3.2.2 预防

* 接口增加校验,校验数据合法性
* 可以将不存在的key 设置为null,并设置短暂的过期时间
* 通过通过位图bit或布隆过滤器实现拦截

3.3 雪崩

3.3.1 介绍

大量的key设置了相同的过期时间,导致缓存在同一时间全部失效,造成大连db请求,压力剧增

3.3.2 预防

* 设置随机过期时间
* 热点数据永不过期
* 定时任务定期更新缓存

4、redis的持久化

4.1 介绍

redis 是内存数据库,如果没有设置持久化redis重启后会出现数据丢失,因此将开启redis的持久化功能,将数据保存在硬盘上,当重启后可以从硬盘中恢复数据,主要有两种持久化方式RDB(redis database)和AOF(append only file).

4.2 RDB(redis database)

4.2.1 介绍

在指定的时间间隔内将内存钟的数据集以快照的方式写入硬盘,生成dump.rdb文件

4.2.2 备份方式和原理

1) save
	调用save,会阻塞redis服务器,执行save命令期间不可以执行其他命令,知道rdb动作完成为止。

2) bgsave
	调用bgsave,会创建响应的fork子进程,由子进程进行,在后台异步进行快照操作

3) 自动化配置
	修改配置文件来完成,配置出发redis rdb持久化条件(save m n 表示m秒内存在n次修改时自动触发bgsave)。

4)主从
	部署主从架构,从服务器进行同步数据的时候,会发送sync执行同步操作,主服务器就会执行bgsave

4.2.3 优缺点

优点:
* 全量备份,适用于进行备份和灾难恢复
* 在大数据量恢复的试试比aof快
* 生成的是一个二进制压缩文件

缺点:
* 每次快照是一次全量备份,fork子进程会后台进行操作,存在开销,数据集大的情况会很耗时间
* 在快照持久化期间修改的数据不会被保存,可能存在数据丢失

4.2.4 核心配置

dir:持久化文件路径
dbfilename : 文件名字(xxx.rdb)

4.3 AOF(append only file)

4.3.1 介绍

追加文件的方式,以独立日志的方式记录记录每次写的命令,重启时在重新执行aof文件中的命令达到恢复数据的目的,写入过程党纪,也步影响之前的数据,可以通过redis-check-aof检查修复

4.3.2 备份方式和原理

通过记录每次执行命令的方式进行备份(3种方式)

1)appendfsync always
 每次有数据修改发生时都会写入aof文件,存在性能消耗

2) appendfsync eversec
 每秒中同步一次

3) appendfsync no
 不主动同步由操作系统自动调度刷磁盘,性能是最好,但也是最不安全的

核心原理
* redis 每次写入命令会之最佳到aof_buf(缓冲区)
* aof缓冲区根据对应的策略向硬盘做同步操作
* 高频aof会带来影响

4.3.3 核心配置

appendonly yes 开启,默认不开启
appendfilename 文件名(默认文件名appendonly.aof路径与rdb路径相同)

4.3.4 aof重新rewrite

1)介绍
* aof文件随着追加会越来越大,需要定期对aof文件进行重写达到压缩
* 旧的aof文件含有无效命令会被忽略,保留最新的数据命令
* 多条命令可以合并成一个命令
* aof重写会降低文件的占用空间
* 更小的aof文件可以更快的被redis加载

2)rewrite重写配置

手动触发:
	直接调用bgrewrireaof命令

自动触发:
	配置auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage参数

	auto-aof-rewrite-min-size: 表示文件最小重写大小,当文件大于该值时才可以重写,默认64m

	uto-aof-rewrite-percentage: 表示当前aof文件空间和上一次重写aof文件空间的比值

4.3.5 优缺点

优点:
	* 数据更加安全
	* 当aof文件太大时,redis能够在后台自动重写aof文件
	* 可以包含所有的操作日志

缺点:
	* aof文件通常比数据集的等效rdb文件大
	* 根据恢复的策略,恢复的时候aof可能比rdb慢

5、redis key过期时间删除策略

5.1 背景

  • redis的key配置过期时间是怎么被删除的?

  • redis的数据明明过期了,怎么还占用这内存?

  • redis 就只能用10g,往里面写20g的数据会发生啥,会淘汰那些数据?

5.2 过期策略

5.2.1 定期删除

每隔一段时间就随机抽取⼀些设置了过期时间的key,检查其是否过期,如果过期就删除,地当期删除可能会导致很多过期key到了时间并没有被删除掉

5.2.2 惰性删除

当客户端尝试访问时,key会被发现并且主动的过期,每次从键空间钟获取键时都会检查取得的key是否过期,如果过期的话就会删除key

备注:使用惰性删除和定期删除这两种策略,通过配合使用服务器可以合理的使用cpu时间和避免浪费内存空间之间取得平衡

5.3 redis的key内存淘汰策略

5.3.1 策略

  • volatile-lru(least recently used)
    最近最少使用算法,从设置了过期时间的键中选择【最长时间未使用】的key清除掉

  • volatile-lfu(least frequently used)
    最近最不经常使用算法,从设置了过期时间的key中选择某段时间之内【使用频次】最小的key清除掉

  • volatile-ttl
    从设置了过期时间key中选择过期时间最早的key清除掉

  • volatile-random
    从设置了过期时间的key中,随机选择key进行清除

  • allkeys-lru
    最近最少使用算法,从所有key中选择最长时间未使用的key清除掉

  • allkeys-lfu
    最近最不经常使用算法,从所有key中选择某段时间之内【使用频次】最小的key清除掉

  • allkeys-random
    从所有key钟随机选择key进行清除

  • noeviction
    不做任何清理工作,在内存超过限制之后,所有写的操作都会返回错误,读操作正常

设置策略
config set maxmemory_policy volatile-lru

6、redis的高可用

6.1 主从复制

6.1.1 意义

  • 相对于单机部署可以提高响应的可靠性,更好的利用cpu
  • 扩展主节点的读能力,分担主节点的压力
  • 一旦主节点宕机,从节点作为住节点的备份可以随时顶上来使用(可以一主多从)

6.1.2 架构

请添加图片描述

6.1.3 主从原理

主从复制分为2种(主从首次时进行全量同步,全量结束后,会进行增量同步):

1)全量同步

  • 主节点会开启一个后台进行用于生成一个rdb文件
  • 主服务器会缓存所有接收到客户端的写命令,当后台进程处理完毕后,会把rdb文件传递给从节点
  • 从节点会将rdb文件保存到硬盘并通过读改文件将数据加载到内存
  • 后续住节点服务器会将此后缓存的命令通过redis传输协议发送给从节点服务器
  • 从节点服务器将这些命令依次作用于自己本地的数据集上,完成数据的一致性

2)增量同步

  • 从服务器完成全量同步后,开始正常工作,主服务器发生操作同步到服务器
  • 主服务器每次执行一个命令都会向从服务器发送相同的命令,从服务器收到命令并执行

注意:从节点不会让key过期,而是主节点过期后将命令发送给从节点,从节点才会删除

6.2 哨兵模式(sentinel)

6.2.1 介绍

哨兵是一个独立的进程,通过发送命令给多个节点,等待其他redis服务器响应,从而达到监控运行的多个redis实例运行情况,当哨兵监测到主节点宕机,会自动将从节点切换为主节点,通过通知其他服务器,修改配置文件切换主机。解决主从架构故障自动迁移的问题。

6.2.2 意义

1) 监控
哨兵会不断的检查你的主服务器和从服务器是否运行正常

2)提醒
当被监控的某个redis服务器出现问题的时候,哨兵可以通过api向管理员或者其他应用程序发送响应通知

3)故障转移

  • 当主服务器不能正常工作时,哨兵会开始一次故障转移,会将从服务器的一个节点升级为主服务器,并让其他从服务器向新的主服务器复制
  • 当客户端访问失效的主服务器时,集群也会向客户端返回新主服务的地址

6.2.3 架构

请添加图片描述

6.2.4 多哨兵模式

一个哨兵进程监控redis会出现单点问题,所以一般采用多个哨兵进行监控,每个哨兵之间还会进行监控,从而达到多哨兵的模式

1)主观下线(Subjectively down 简称:SDOWN)

  • 是单个哨兵对服务器做出的判断,例如网络问题无法接收到通知
  • redis服务器在没有接收到,dowm-after-miliseconds选项所指定的时间内,对给它发送ping命令的哨兵返回一个有效回复(valid reply),那么哨兵就会将这个服务器标识为主观下线(直白说哨兵主动跟服务器联系,但是没有收到回复就认为你下线了,实际并不一定下线)

2)客观下线(Objectively dowm 简称 ODOWN)

  • 多个哨兵对同一个redis服务器做出的sdown判断,并通过哨兵 is-master-down-by-addr 命令互相交流之后得出的服务器下线判断
  • 一个哨兵通过想另一个哨兵发送 is-master-down-by-addr 命令来寻味对方是否认为给定的服务器已下线(白话:张三问李四,服务器a你觉得他下线没,李四说下线了)
  • 仅仅使用与主服务器

3)仲裁(qurem)

  • 哨兵在给定的时间内从其他哨兵哪里接收到【足够数量】的主服务器下线的报告,那么哨兵就会将主服务器的状态从主观下线变成客观下线
  • 【足够数量】为配置文件内的值,一般配置的是 总哨兵个数的一半+1,例如3个哨兵设置为2
  • down-after-milliseconds 是哨兵在超过规定的时间依旧没有得到响应后,会自己认为不可以
  • 当主观下线的哨兵达到设置的配置数量时,就会发起一次投票,进行failover

6.3 集群模式(cluster)

6.3.1 介绍

采用无中心架构设计,每隔节点保存的数据和整个集群的状态,每隔节点都和其他节点连接互相通信,
至少6个节点才能保证搞可用(3主3从 主从节点自动分配),数据分散存储在每隔节点上

6.3.2 数据分片和虚拟哈希槽

  1. 哈希槽(slot):redis预先分配好16384个槽,当需要在redis集群钟放置一个key-value时,根据CRC16(key)%
    16384的值 决定将一个key放在哪个槽中
  2. 流程
    以3个主节点为例,将16384个槽分配到3个节点,节点1(0-5460)节点2(5461-10922)节点3(10923-16383)
    对哟啊存储或查找的key进行crc16哈希运算得到一个值,并通过16384取模运算,判断这个值在哪个范围区间

后续补充部署实操部分…
敬请期待!!!

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值