Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)

文章目录

    • 一、Redis的简介
      • 1.1 Redis基本信息
      • 1.2 Redis的优点
      • 1.3 Redis的8个应用场景
      • 1.4 Redis是单线程
    • 二、Redis的基本操作
        • 1 select:
        • 2 dbsize:
        • 3 keys
        • 4 flushdb
        • 5 flushall
    • 三、Redis基于基本数据类型的命令
      • String:字符串
        • 1 set
        • 2 get
        • 3 exists
        • 4 append
        • 5 strlen
        • 6 incr & decr
        • 7 incrby & decrby
        • 8 setrange & getrange
        • 9 setex & ttl
        • 10 setnx
        • 11 mset & mget
        • 12 getset
      • Hash:哈希
        • 1 hset & hget
        • 2 hmset & hmget
        • 3 hgetall
        • 4 hdel
        • 5 hlen
        • 6 hexists
        • 7 hkeys & kvals
        • 8 hincrby
        • 9 hsetnx
      • List :列表
        • 1 lpush & rpush & lrange
        • 2 lpop & rpop
        • 3 lindex
        • 4 llen
        • 5 lrem
        • 6 ltrim
        • 7 rpoplpush
        • 8 lset
        • 9 linsert
      • set:集合
        • 1 sadd
        • 2 smembers
        • 3 sismember
        • 4 scard
        • 5 srem
        • 6 srandmember
        • 7 spop
        • 8 smove
        • 9 sinter & sunion & sdiff
      • SortSet:有序集合
        • 1 zadd
        • 2 zrangebyscore
        • 3 zrem
        • 4 zcard
        • 5 zcount
      • 四、应用场景
        • 1 缓存
        • 2 数据共享
        • 3 分布式锁
        • 4 全局ID
        • 5 计数器
        • 6 限流
        • 7 Top问题
        • 8 消息队列
        • 9 用户关注,推荐模型
        • 10 排行榜
      • 五、Redis特殊类型
        • 1 geoadd & geopos
        • 2 geodist
        • 3 georadius
        • 4 georadiusbymember
      • 六、Redis持久化
        • 1 RDB
          • 1 save
          • 2 bgsave
          • 2 触发RDB方式
          • 优点
          • 缺点
        • AOF(Append Only File)日志文件
          • AOF回写策略
          • 优点
          • 缺点
      • 七、Redis事务
        • 1 Redis事务机制
      • 八、Redis内存淘汰机制
        • 1 内存维护的解决方案
        • 2 过期策略
        • 3 内存淘汰机制
      • 九、Redis缓存数据一致性及问题
      • 1 保证缓存和数据库数据一致性
        • 2 缓存问题
          • 1 缓存穿透(查不到)
          • 2 缓存击穿(量太多)
          • 3 缓存雪崩
      • 十、Redis高可用
        • 1 主从复制
          • 复制原理
          • 主从复制配置
        • 哨兵模式
          • 哨兵模式的内容
          • 工作过程
          • 哨兵原理
          • 哨兵故障修复原理

一、Redis的简介

1.1 Redis基本信息

  1. Redis是当前互联网世界最流行的NoSQL(Not Only SQL)数据库,NoSQL在互联网系统中的作用很大,因为它可以在很大程度上提高互联网的性能。
  2. Redis具备一定持久层的功能,也可以作为一种缓存工具,对于NoSQL数据库而言,作为持久层,它存储的数据是半结构化的,这就意味着计算机在读入内存中有更少的规则,读入速度更快。
  3. 对于那些结构化,多范式的数据库系统而言,它更具性能优势,作为缓存,它可以支持大数据存入内存,只要命中率高,他就可以快速响应,因为在内存中的数据读写数据库读写磁盘的速度快几十甚至到上百倍。

1.2 Redis的优点

  1. 因为数据库系统有更好的规范性和数据完整性,功能更加强大,作为持久层更为完善,安全性能也更高,而NoSQL结构松散,不完整,功能有限,但是作为缓存工具,它的高性能,高响应等功能,使它成为一个很重要的工具。
  • Redis响应非常快:
    • 每秒可以执行大约110000个写入操作,或者81000个读操作,其速度远超数据库,如果存入一些常用的数据,就能有效提高系统的性能。
  • 支持6种数据结构
    • 他们是字符串,哈希结构,列表,集合,可排序集合和基数。比如对于字符串可以存入一些java数据类型,哈希可以存储对象,列表可以存储List对象等,这使得在应用中很容易根据自己的需要选择存储的数据类型,方便开发。
  • 操作都是原子性的
    • 所有的Redis操作都是原子性的,从而确保当两个客户同时访问Redis服务器时,得到的是更新后的值,在需要高并发的场合可以考虑使用Redis的事务,处理一些需要的业务。
  • MultiUtility工具
    • Redis可以在如缓存,消息队列中使用(Redis支持“发布+订阅”的消息模式),在应用程序如Web应用程序会话,网站页面点击数等任何短暂的数据中使用。
    • NOSQL从数据库中读取数据进行缓存,就可以从内存中读取数据了,而不像数据库一样读磁盘,现实是读操作远比写操作要多的多,所以缓存很多常用的数据,提高其命中率有助于整体性能的提高,并且能减缓数据库的压力,对互联网系统架构是十分有利的。
    • 另一方面,他也可以满足互联网高并发需要告诉处理数据的场合,比如抢红包,商品秒杀等场景,这些场合需要告诉处理,并保证并发数据安全和一致性。
  • Redis都是单线程的,避免线程切换来校以及线程竞争的为题
  • 支持持久化,Redis总共支持RDB和AOF两种出久华方案,持久化有效避免了数据丢失的问题;
  • 支持事务,
  • 支持主存复制,主节点将数据通过步给从节点,可以进行读写分离;

1.3 Redis的8个应用场景

  • 缓存-热数据
    • 热点数据(经常会被查询,但是不经常被修改或者删除的数据),首选是使用Redis缓存,毕竟强大到冒泡的QPS和极强的稳定性不是所有类型工具都有的,而且相比于memcached还提供了丰富的数据类型可以使用,另外内存中的数据提供了AOF和RDB等持久化机制可以选择。
  • 计数器
    • 注入统计点击数等应用,由于是单线程,可以避免并发问题,保证不会出错,而且100%毫秒级性能。
  • 位操作(大数据处理)
    • 用于数据量上亿的场景下,例如几亿用户系统签到,去重登陆次数统计,某用户是否在线状态等等;
  • 分布式锁与单线程机制
    • 验证前端的重复请求(可以自由扩展类似情况),可以通过Redis进行过滤,每次请求将request ip、参数、接口等hash作为key存储在Redis,设置多长时间的有限期,然后下次请求过来的时候现在Redis中检索有没有这个key,进而验证是不是一定时间内过来的重复提交秒杀系统,基于Redis是单线程特征,防止出现数据库爆破全局增量ID生成,类似秒杀。
  • 最新列表
    • 如新闻列表页面更新的新闻列表;
  • 排行榜
    • 谁得分高排名往上,
  • 使用场景
    • 数据的高并发的读写;
    • 海量数据的续写;
    • 对扩展性要求高的数据;

1.4 Redis是单线程

  1. Redis是基于内存操作的,CPU不是Redis的性能瓶颈,Redis的性能问题来自于机器内存和网络宽带,既然可以使用单线程来实现,那么就使用单线程。
  2. 单线程的好处
    • 避免了过多的上下文的切换的开销
    • 避免同步机制的开销,如果是多线程模型,需要考虑数据同步的问题,必然引起同步机制,如锁机制,增加程序的复杂度;
    • 实现简单,方便维护

二、Redis的基本操作

  • Redis中默认有16个数据库(从0到15),默认使用第0个数据库,可以通过select进行切换。
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第1张图片

1 select:

  • 切换数据库 ,返回值为OK,即切换数据库成功;
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第2张图片

2 dbsize:

  • 查看当前数据库中数据的个数,set方法是往数据库中写入数据(返回为OK则表示写入成功)
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第3张图片

3 keys

  • 查看所有的key,
    在这里插入图片描述

4 flushdb

  • 清空当前数据库,
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第4张图片

5 flushall

  • 清空所有数据库,

三、Redis基于基本数据类型的命令

String:字符串

  1. String类型是Redis中的基本类型,一个key对应一个value;
  2. String类型的值可以使字符串,数字或者是二进制的数据,最大不超过512M;

1 set

  • 添加数据
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第5张图片

2 get

  • 通过key获取值
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第6张图片

3 exists

  • 判断key是否存在,存在返回1,不存在返回0;
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第7张图片

4 append

  • 追加字符串,如果key存在,就追加,如果key不存在,相当于set;
    在这里插入图片描述

5 strlen

  • 获取字符串的长度
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第8张图片

6 incr & decr

  • 对value进行自增加1(自减减1)操作;
  • 注意,这里只能对基本数据类型进行操作,字符串会报错
  • 如果key不存在,那么value的值先会被初始化为0,然后再进行自增或自减操作;

Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第9张图片

7 incrby & decrby

  • 设置加减的步长,也就是以多少步长进行自增和自减;
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第10张图片

8 setrange & getrange

  • 从指定位置开始替换字符串中的值,返回值表示value的长度;
    在这里插入图片描述

9 setex & ttl

  • 设置过期时间,查看剩余时间
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第11张图片

10 setnx

  • 如果key不存在则设置,否则失败不设置,当key存在的时候,就返回1,不存在就返回0;可以基于setnx实现分布式锁。
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第12张图片

11 mset & mget

  • 批量的插入数据和批量的获取数据
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第13张图片

12 getset

  • 先获取值,然后再设置值;如果成功,则返回原来的值,否则返回空(nil);
    在这里插入图片描述

Hash:哈希

  • hash类型适合存储对象,hash的命令都是以h开头的

1 hset & hget

  • 设置数据和获取数据
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第14张图片

2 hmset & hmget

  • 批量化的设置数据和获取数据;
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第15张图片

3 hgetall

  • 获取key中的所有的value值;
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第16张图片

4 hdel

  • 删除指定的filed的hash键值对
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第17张图片

5 hlen

  • 获取hash中键值对的个数;
    在这里插入图片描述

6 hexists

  • 判断hash中字段是否存在,不存在的时候返回0,存在的时候返回1;
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第18张图片

7 hkeys & kvals

  • 获取hash中的所有的filed和获取hash中的所有的value;
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第19张图片

8 hincrby

  • 给定hash中字段的值加上一定步长,
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第20张图片

9 hsetnx

  • 如果存在,则添加成功,返回1;否则,添加失败返回0
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第21张图片

List :列表

  • 列表是简单的字符串列表,按照插入的顺序进行排序,数据是可以重复的,可以在头部和尾部进行插入和删除;
  • 类似于java中的LinkedList集合
  • 可以使用该类型的实现栈,队列等数据结构

1 lpush & rpush & lrange

  • 从列表的左边插入和从列表的右边进行插入
  • 查看从list中获取指定范围内的数据的个数
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第22张图片

2 lpop & rpop

  • 从左边或者从右边删除数据
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第23张图片

3 lindex

  • 获取指定下标的值
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第24张图片

4 llen

  • 获取list中元素的个数
    在这里插入图片描述

5 lrem

  • 删除list中的元素
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第25张图片

6 ltrim

  • 截取列表中的值
    在这里插入图片描述

7 rpoplpush

  • 移除列表中的最后一个元素,将它添加到另外一个list中
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第26张图片

8 lset

  • 根据下标替换列表中的值
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第27张图片

9 linsert

  • 在列表中插入值,在指定元素前或者后插入数据, 如果指定的数据重复,只找到第一个出现的元素在其前后进行插入即可;
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第28张图片
  • 使用列表完成数据结构
    • 实现栈(先进后出):lpush+lpop
    • 实现队列(先进先出):lpush+ rpop
    • 有限集合:lpush+ ltrim

set:集合

  • Redis中的set是String类型的无序集合,数据是无序的,并且属性元素是唯一的,意味着不能出现重复元素
  • 命令的开头以s开头

1 sadd

  • 给set中添加元素,当集合中元素不存在的时候,添加成功返回集合中的元素个数,如果添加的元素重复,就会返回0.
    在这里插入图片描述

2 smembers

  • 获取set中的所有的值
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第29张图片

3 sismember

  • 判断某个元素是否在set中,如果在set中,就返回1,不存在就返回0;
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第30张图片

4 scard

  • 获取set中的元素的个数
    在这里插入图片描述

5 srem

  • 删除set中的元素
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第31张图片

6 srandmember

  • 从set中随机获取值
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第32张图片

7 spop

  • 随机删除指定元素格式
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第33张图片

8 smove

  • 将指定元素从一个set中移动到另一个set中
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第34张图片

9 sinter & sunion & sdiff

  • 分别求交集,并集,补集;
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第35张图片Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第36张图片

SortSet:有序集合

  • sortSet和set类似,集合中数据元素不能重复,
  • 有序集合可以实现元素排序,给定内个元素设置一个分数,作为排序的依据
  • 有序集合中的元素不能重复,但是分数是可以重复的。
  • 有序卷积核一般以Z开头

1 zadd

  • 添加元素
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第37张图片

2 zrangebyscore

  • 按照zset从小到大进行排序
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第38张图片

3 zrem

  • 删除zset中的元素
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第39张图片

4 zcard

  • 查看zset中元素的个数
    在这里插入图片描述

5 zcount

  • 更具score的值统计在给定区间的元素个数
  • 应用场景,如排行榜,按照时间序列的新闻等等;
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第40张图片

四、应用场景

1 缓存

  1. 一般使用String类型
  2. 缓存热点数据,对象缓存,页面缓存,降低数据库压力;

2 数据共享

  1. Redis相对于引用数据是独立服务,可以在多个应用之间共享;

3 分布式锁

  1. String类型的setnx只有在不存在的情况下才能添加成功

4 全局ID

  1. 给定一个全局发号器,依次给定一段号,每个服务器使用完再来申请,incrby通过步长设置来获取,利用Redis操作的原子性。

5 计数器

  1. incr方法:如文章阅读量,微博的点赞量

6 限流

  1. 一般通过访问的ip加其他信息作为一种key,访问依次加1,超过设定的阈值直接返回

7 Top问题

微博热搜按照访问量zset处理

8 消息队列

  • list提供了两端操作的方法,rpush,lpush,rpop,lpop等操作
  • 通过操作可以实现队列栈等结构

9 用户关注,推荐模型

  • sdiff():获取差集,推荐(好友推荐,粉丝推荐,关注话题推荐)
  • sinter():获取交集,(共同好友,共同话题)
  • sunion():获取并集(所有好友,所有话题)

10 排行榜

  1. 新闻排行榜,微博热搜

五、Redis特殊类型

  • geospatial地理空间
  • 主要用于存储地理位置的信息,并对存储的信息进行操作;
  • 适用场景如:定位,附近的人

城市经纬度查询

1 geoadd & geopos

  • 添加地理位置,添加经度,纬度,名称

Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第41张图片

2 geodist

  • 返回两个给定位置之间的距离
    在这里插入图片描述

3 georadius

  • 以给定的经纬度为中心,找到一个半径内的元素
    在这里插入图片描述

4 georadiusbymember

  • 以一个成员为中心,查找指定范围内的元素
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第42张图片

六、Redis持久化

  • 持久化的内涵就是直数据的安全性问题,将内存数据存储到磁盘当中,这就是所说的持久化的问题;
  • 持久化有两种方式,一种是RDB,另一种是AOF。

1 RDB

  1. 内存快照

    • 内存中数据在某一时刻的状态记录;
    • Redis中默认的持久化方案;
    • 将内存中的数据写入到磁盘中,在指定的目录下生产一个dump.rdb文件;
    • Redis重启时会加载dump.rdb文件恢复数据
  2. Redis中的两种生成RDB文件的两个命令

1 save
  • 在书进程中执行,会导致阻塞;
2 bgsave
  • 创建一个子进程,用户写入RDB文件,避免了主线程的阻塞,该方法是RDB文件生成的默认设置;
  • 命令的执行原理
    • 执行执行bgsave命令;
    • Redis中的父进程判断当前是否存在正在执行的子进程,如果存在,命令直接返回;
    • 父进程fork操作创建子进程;
    • 父进程完成fork操作之后,父进程可以继续接受并处理用户请求,而子进程负责将内存中的数据写入到磁盘中零时文件;
    • 当子进程完成所有数据写入后会用零时文件替换旧的RDB文件;
      Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第43张图片
2 触发RDB方式
  1. 手动触发
    • 用户执行save或者bgsave命令;
  2. 被动触发
    • 根据配置的规则进行自动快照;
  3. 恢复RDB文件的方式
    • 将RDB文件放在Redis的启动目录下,Redis启动时就会自动检查dump.rdb文件恢复其中的数据;
优点
  1. RDB加载Redis恢复数据远远快于AOF的方式;
  2. 使用单独的子进程来进程持久化,主进程不会进行任何的IO操作,保证Redis的高性能
缺点
  1. RDB方式数据无法做到实时持久化,可能会存在数据丢失问题;
  2. 存在格式不兼容问题,RDB文件使用特定二进制格式保存,Redis在版本升级后,可能存在老版本Redis无法兼容新版本RDB格式问题;

AOF(Append Only File)日志文件

  • AOF持久化

    • 以独立的日志的方式记录每次写命令,热镀丝重启是会重新执行AOF文件中的命令达到回复数据的目的;
    • AOF主要作用是解决数据持久化的实时性。
    • 默认情况下Redis没有开启AOF方式的持久化,可以通过appendonly参数启用:apendonly yes,开启AOF方式持久化每执行一条命令,Redis就会将命令写入到aof_buff缓冲区,AOF缓存去会根据对应的策略向磁盘做同步操作
      默认情况在30秒就会执行一次同步操作,为了防止缓冲区数据的丢失。
  • AOF持久化执行流程

    • 所有的写入命令会追加到AOF缓冲区;
    • AOF缓冲区根据对应的策略向磁盘同步;
    • 随着AOF文要件越来越大,需要定期对AOF文件进行重写,达到压缩文件体积的目的,AOF文件重写是吧Redis进程内的数据转化为写命令同步新AOF;
    • 当Redis进行重启时,可以加载AOF文件进行数据恢复
    • AOF保存文件:appendonly.aof;
      Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第44张图片
AOF回写策略
  • AOF的三种方式
    • always:同步写回,每个写命令执行完,立马同步将日志写回磁盘,保证完全持久化,最慢;
    • everysec:每秒写回:每个命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区的数据写入磁盘;
    • no:操作系统控制写回:每个命令执行完,先把日志写到AOF文件的内存缓冲区,由操作系统决定何时从缓冲区写回此判断,性能最好,持久化没法保证
优点
  1. AOF可以更好的保护数据不丢失,可以配置AOFeverysec操作,每秒执行一次,如果Redis挂掉,最多丢失1秒的数据;
  2. AOF是以Append-only的模型写入,没有磁盘寻址的开销,写入性能比较高;
缺点
  1. 对于同一份文件AOF文件比RDB数据快照要大;
  2. 数据恢复比较慢;

七、Redis事务

  1. Redis事务可以一次性执行多条命令;
  2. Redis就是一次性,顺序性,排他性的执行一个队列中的一系列命令;
  3. Redis不保证原子性;
  4. Redis中,单条命令是原子执行的,但是事务不保证原子性,且没有回滚的概念,事务中任意命令执行失败,其余的命令仍会执行;
  5. Redis事务是没有隔离级别的概念;
  6. 批量操作在发送exec命令前被放入队列,并不会被执行,也就不存在事务内的查询要看到事务里的更新事务外查新不能看到;
  • 事务命令
    • DISCARD:取消执行事务快内的所有命令;
    • EXEC:执行所有事务快的命令;
    • MULTI:标记一个事务块的开始;
    • UNWATCH:取消WATCH命令对所有key的监视;
    • WATCH key [key…]:监视一个或多个key,如果在事务执行之前这个key被其他命令所改动,那么事务将被打断;

1 Redis事务机制

  1. 将批量操作的命令放入到队列中进行缓存,再执行exec命令之后才会进入到事务中,事务中任意命令执行失败,其余命令依然被执行
  2. 在事务执行过程中,其他客户端提交的命令请求是不会被插入到事务执行命令的序列中
  3. 一个事务从开始到执行主要是三个阶段
    • 开启事务:multi
    • 命令入队列
    • 执行事务:exec
  4. 在执行exec之前,所有的命令在事务队列中,并没有直接被执行,只有发起执行命令才会执行
  5. 正常事务执行
    • Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第45张图片
    • discard:放弃事务,如果放入事务队列中的命令错了可以放弃事务的执行,使用discard命令队列中的所有命令都不会执行;
      Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第46张图片
    • 执行时异常:执行时异常,如果事务队列中存在错误的语法,在事务执行的时候,其他命令都可以正常执行,错误的命令抛出异常;

Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第47张图片

  1. 编译时异常
    Redis知识详解(由浅入深,满足你对Redis的基本能理解和操作)_第48张图片
  2. watch命令:监视一个或多个key,如果在事务执行之前key被其他命令所修改,那么事务将被打断,可以当做乐观锁使用;

八、Redis内存淘汰机制

  • 在Redis作为缓存使用过程中,当内存不足时,redis根据配置进行缓存淘汰绝大部分key,保证后续写入能成功;

1 内存维护的解决方案

  1. redis的配置中没有设置最大的内存大小;
  2. 如果Redis没有设置最大内存大小或者设置为0,在64操作系统下Redis不限制使用内存大小,在32位操作系统下最多使用3/4内存空间;
  3. 内存操作命令:
    • config get maxmemory :查看最大内存情况;
    • config set maxmemory value :设置大小;
    • info memory :查看当前Redis内存使用命令;
  4. 内存维护方案
    • 过期策略:用户处理过期的缓存数据;
    • 内存淘汰机制:内存空间不足时需要额外申请空间的数据;

2 过期策略

  1. 定期过期:
    • 对每个设置过期时间的key都需要建一个定时器,到达过期时间会立即清除。该方法对内存友好,对CPU不优化,会占用大量的CPU资源去处理过期数据;
  2. 惰性过期:
    • 只有当访问一个key时,才会判断key是否过期,该方案最大化的节省CPU资源,但会占用内存资源(对CPU友好,对内存不友好);
  3. 定期过期:
    • 每隔一定的时间,会扫描一定数据的expires字典中的一些数据,并清除掉其中已过期的数据;
      expires字典会保存所有设置过期时间的数据;

3 内存淘汰机制

  1. 在内存不足时(内存使用已经超过mexmemory参数设定值是),需要处理新写入的且需要申请格外的空间的数据;
    • volatile-lru:从设置过期时间的数据集中(expries)中挑选出最近最少使用的数据淘汰;
    • volatile-ttl:从设置过期时间的数据集中(expires)中挑选中将要过期的数据淘汰,ttl的值越大越优先被淘汰;
    • volatile-random:从设置过期时间的数据集(expries)中随机的选取数据淘汰;
    • allkeys-lru:从数据集(dict)中挑选最近最少使用的数据淘汰,该策略要淘汰的数据是全体key的集合,而非过期的key;
    • allkeys-random:从数据集(dict)中选择任意数据淘汰;
    • noeviction:禁止删除数据,当内存不足时,新写入操作就会报错,请求可以继续进行,保证已插入的数据不会丢失;
  2. 主要策略
    • LRU策略(最近最少使用):核心思想,如果数据最近被访问过,那么将来被访问的几率也就会越高;
    • TTL策略:在Redis中设置过期时间的数据集expries中挑选数据,根据ttl 过期时间来进行淘汰,值越大越先淘汰;
    • 随机策略:在数据集中随机数据的获取进行删除
    • LFU策略:Redis 4.0中新增策略,(最近最少使用)核心思想:如果数据在最近一段时间很少被访问到,那么认为数据在将来被访问的可能性也比较小,因此,当空间满时,最小访问频率的数据会被最先淘汰;
  3. LRU和LFU的不同
    • LRU是最近最少使用页面置换算法(Least Recently Used),也就是首先淘汰最长时间未被使用的页面!
    • LFU是最近最不常用页面置换算法(Least Frequently Used),也就是淘汰一定时期内被访问次数最少的页!

九、Redis缓存数据一致性及问题

1 保证缓存和数据库数据一致性

  1. 缓存数据插入时机(对于服务器):
    • 首先到缓存查询数据,如果数据存在则直接获取数据返回;
    • 如果缓存不存在,需要查询数据库,从数据库获取数据并插入缓存,将数据返回;
    • 当第二次查询时,后续查询操作就可以查询缓存数据;
  2. 更新数据时操作
    • 先删除缓存在更新数据库;
      • 进行更新数据库数据时,先删除缓存,然后更新数据库,后续的请求再次读取数据时,会从数据库中读取数据更新到缓存;
      • 存在问题: 删除缓存之后,更新数据库之前,这个时间段内如果有新的请求过来,就会从数据库中读到旧的数据写入缓存,再次造成数据不一致,并且后续读操作都是旧数据;
    • 先更新数据库在删除缓存;
      • 进行更新操作,先更新数据库,成功之后,在删除缓存,后续请求将新数据写回缓存;
      • 存在问题: 更新MySQL和删除缓存这段时间内,请求读取的还是缓存内的旧数据,不过等数据库更新完成后,就会恢复一致;
    • 异步更新缓存
      • 数据库的更新操作完成后不直接操作缓存,将操作命令封装成消息放到消息队列里,然后由Redis自己去更新数据,消息队列保证数据操作数据的一致性,保证缓存数据的数据正常;

2 缓存问题

1 缓存穿透(查不到)
  • 用户想查询一个数据,发现Redis中没有,也就是缓存没有命中,就像持久性数据库发起查询,发现数据库也没有这个数据,于是查询失败了,当用户请求很多的情况下,缓存没有命中,数据库也没有数据,会给数据库造成很大的压力,这就是缓存穿透;
  • 解决方案:
    • 使用布隆过滤器: 使用之后将存储的数据放入布隆过滤器,每次数据查询首先查询布隆过滤器,当在过滤器中判断存在时在到数据库缓存查询,如果没有进入数据查询,如果在过滤器不存在,则直接返回告诉用户该数据查不到,这样能大大减轻数据库查询压力;
    • 缓存空对象: 当数据库数据不存在时,及时返回的空对象也缓存起来,同时设置一个过期时间,之后在访问数据将从缓存中获取,保护了数据库;
  • 存在问题:
    • 对空值设置过期时间,会存在更新数据库数据到缓存数据失效的一段时间,缓存数据有问题,会对要保证数据一致性的业务造成影响;
    • 会需要更多的空间来存储更多的控制,造成内存中有大量的空值的键;
2 缓存击穿(量太多)
  • 指一个key是一个热点key,在不停的扛着大量的并发,当key在失效的瞬间,持续的大并发就会穿破缓存,直接请求到数据库。对数据库造成瞬间压力过大;
  • 解决方案:
    • 热点数据永不过期: 从缓存角度看,没有设置过期时间,就不会存在花村过期之后产生的问题;
    • 加互斥锁: 用分布式锁,保证对每个key的访问同一时刻只能一个线程去查询后端服务,其他没有获取锁权限的线程则等待即可;
3 缓存雪崩
  • 缓存雪崩是指在某一个时间段,缓存集中过期失效或者Redis宕机;
  • 对于数据库而言,所有请求压力会全部到达数据库,导致数据库调用量暴增,可能也造成数据库宕机的情况;
  • 解决方案:
    • Redis采用高可用
      • 思路就是将数据在Redis中存放在服务器上,及时一个服务器挂掉,其他服务器还可以继续工作;
    • 限流降级
      • 在缓存失效后,通过加锁或者队列来控制读取数据库的线程数量让线程在队列排队,控制整体请请求速率;
    • 数据预热
      • 在正是部署服务之前,先访问一遍数据,可以将大部分的数据加载到缓存中,在即将发生大并发之前已经加载不同的key,设置不同的过期时间,让缓存失效的时间更加均匀;

十、Redis高可用

1 主从复制

  1. Redis的复制功能是支持将多个数据库之间进行数据同步;
  2. 主数据库可以进行读写操作,当主数据库数据发生改变时会自动同步到从数据库,
  3. 从数据库一般是只读的,会接收注数据库同步过来的数据。
  4. 一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库;
  5. 默认情况下,每台服务器都是主节点,可以通过配置来设置Redis节点称为从数据库
复制原理
  1. 当启动一个从节点时,它会发送一个psync的命令给主节点;
  2. 如果是从节点初次连接到主节点,会触发一次全量复制,此时主节点会启动一个后台进程,开始生成一个RDB快照文件;
  3. 同时会从客户端收到的新命令写入缓存的内存中,RDB文件生成完成之后,主节点会将RDB文件发送给从节点,从节点会先将RDB文件写入本地磁盘,然后再从本地磁盘上加载到内存中;
  4. 接着主节点会将内存中的缓存的写命令发送给从节点,从节点同步这些数据;
  5. 、如果从节点和主节点之前发生网络故障,连接断开,会自动重连,连接之后主节点会将部分缺失的数据同步给从节点;
主从复制配置
  1. 默认情况下,每个节点都是主节点,只需要配置从节点;
  2. 可以通过复制Redis.conf配置文件,修改主要信息
  3. 端口号 、pid名称、log文件名称、dump.rdb名称;
  4. 可以修改配置,配置就永久有效,也可以通过命令形式做处理;
  5. 命令;
    • info replication:查看当前库信息;
    • slaveof ip port :在从服务器上执行名,给定主服务器的端口和IP;
    • Slave no one :可以让从节点恢复为主机;

哨兵模式

  1. 搭建好的主从复制方案可以达到数据同步目的,但是当主服务器宕机后,需要手动将一个从服务器切换为主服务器,这个过程需要人工干预,同时切换会导致Redis的写入功能不可用。
  2. 需要一种能够自动完成master故障发现并能够将一个Slave切换为master,这个时候需要哨兵sentinel模式,哨兵模式可以自动切换主从节点。
哨兵模式的内容
  1. 当我们搭建好redis主从复制方案后会发现一个问题,那就是当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,同时在手动切过程中也会导致redis服务器写入功能不可用。所以需要一种方法可以完成Master故障后可以自动的将一个Slave切换为Master,这个时候就有了sentinel哨兵模式。通过哨兵机制可以自动切换主从节点。(自动选举老大);
  2. sentinel是官方提供的高可用方案,其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。同时 sentinel是一个分布式系统,可以在一个架构中运行多个Sentinel进程,可以做到sentinel的高可用。
工作过程

● 通过向主服务器和从服务器发送ping命令,让服务器返回运行状态。
● 当哨兵监测到master宕机,会自动将一个slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。

关于sentinel的三个定时任务
● 每1秒每个sentinel对其他sentinel和redis节点执行ping操作,心跳检测。
● 每10秒每个sentinel会对master和slave执行info命令,目的是发现slave结点,确定主从关系。
● 每2秒每个sentinel通过master节点的channel交换信息(pub/sub)。master节点上有一个发布订阅的频道(sentinel:hello)。sentinel节点通过__sentinel__:hello频道进行信息交换(对节点的"看法"和自身的信息),达成共识.

哨兵原理
  1. 一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控,各个哨兵之间还会进行监控,这样就形成了多哨兵模式
  2. sentinel是一个分布式系统,可以在一个架构中运行多个Sentinel进程。所以监控同一个Master的Sentinel会自动连接,组成一个分布式的Sentinel网络,互相通信并交换彼此关于被监视服务器信息。
哨兵故障修复原理
  1. 主观下线:

    • 当主服务器发生故障时,此时一个sentinel发现了故障,系统并不会马上进行failover过程(这个现象称为主观下线),它会向网络中的其他Sentinel进行确认。
  2. 客观下线:

    • 接着其他Sentinel也陆续发现故障,这个时候其中一个Sentinel就会发起投票。一定数量的哨兵(在配置文件中指定)确认Master被标记为主观下线,此时将Master标记为客观下线。
  3. sentinel的leader选举:

    • 要想完成故障切换(将故障master剔除,并将一个slave提升为master)就必须先选举一个leader。最先发现故障的sentinel向其他哨兵发起请求成为leader,其他哨兵在没有同意别的哨兵的leader请求时,就会把票投给该sentinel。当半数以上的sentinel投票通过后就认定该sentinel为leader。接下来的故障切换有该leader完成。
  4. master选举:

    • leader选好后将故障master剔除,从slave中挑选一个成为master。遵照的原则如下:
      ● slave的优先级
      ● slave从master那同步的数据量,那个slave多就优先。
  5. 新Master再通过发布订阅模式通知所有sentinel更新监控主机信息。

  6. 故障的主服务器修复后将成为从服务器继续工作。

  • 哨兵模式的优点
    ● 哨兵集群、基于主从复制模式,所有的主从复制优点,它会有
    ● 主从可以切换,故障可以转移,系统的可用性会更好
    ● 哨兵模式就是主从模式的升级,手动转自动,更加健壮
  • 哨兵模式的缺点
    ● Redis不好在线扩展,集群容量一旦到达上限,在线扩容十分麻烦
    ● 实现哨兵模式的配置很麻烦,里面有很多选择

你可能感兴趣的:(redis,数据库,nosql)