[学习笔记]Redis数据库基础知识

文章目录

    • 什么是NoSQL
      • NOSQL数据库概述
      • NoSQL适用场景
      • NoSQL不适用场景
      • NoSQL四大分类
    • 初识Redis
    • Redis安装
    • redis-benchmark压力测试工具
    • Redis基本命令
    • Redis五大数据类型
      • String
      • List
      • Set
      • Hash
      • Zset(有序集合)
    • 三种特殊的数据类型
      • geospatial
      • Hyperloglog
      • Bitmap
    • Redis的事务
    • Redis的乐观锁
    • Jedis的使用
    • 整合Spring Boot
      • 序列化问题
    • Redis的持久化
      • RDB
      • AOF
    • Redis的发布订阅
    • Redis集群
      • 搭建一个伪分布式用于测试
      • 主从模式的配置
      • 哨兵模式的配置
    • Redis的穿透、击穿和雪崩
      • 穿透
      • 击穿
      • 雪崩

什么是NoSQL

NOSQL数据库概述

  • NoSQL (NoSQL = Not Only SQL ),意即“不仅仅是SQL",泛指非关系型的数据库。

  • NoSQL不依赖业务逻辑方式存储,而以简单的key-value模式存储。因此大大的增加了数据库的扩展能力。

  • 不遵循SQL标准。

  • 不支持ACID。

  • 远超于SQL的性能。

NoSQL适用场景

  • 对数据高并发的读写

  • 海量数据的读写

  • 对数据高可扩展性的

NoSQL不适用场景

  • 需要事务支持

  • 基于sql的结构化查询存储,处理复杂的关系,需要即席查询。

NoSQL四大分类

  • K-V键值对: Redis
  • 文档型数据库: MongoDB、ConthDB
  • 列存储数据库: HBase
  • 图关系数据库: Neoj4j、InfoGrid

初识Redis

Redis是一个开源的key-value存储系统。 和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash (哈希类型)。这些数据类型都支持push/pop、add/remove及 取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis支持各种不同方式的排序。与memcached- 样,为了保证效率,数据都是缓存在内存中。区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis官方网站

Redis中文网站

Redis安装

  1. 官网上有安装入口,这里下载了5.0.8版本

  2. 安装完成后解压,会得到源码文件

  3. 进入redis主目录,运行make命令,编译,运行make install检查是否安装成功

    如果不是root用户,得使用sudo运行上述命令,否则有的目录无法创建
    [学习笔记]Redis数据库基础知识_第1张图片
    出现上图所示,说明安装成功

  4. 修改配置文件,将redis配置成允许后台运行
    在这里插入图片描述

  5. 使用redis-server redis.conf命令启动Redis服务端

    Redis所有命令都被放入/usr/local/bin中,因此全局都可以运行Redis命令

    这个命令需要指定配置文件,因此它参数是配置文件的位置,此时我就在配置文件本路径运行这条命另,因此没写全路径名

  6. 使用redis-cli -p 6379开启Redis客户端,-h指定主机,-p指定端口,默认是本机6379端口
    在这里插入图片描述
    使用ping命令测试服务,返回PONG说明服务正常
    在这里插入图片描述

  7. 使用shutdown命令关闭服务端,使用exit退出客户端
    在这里插入图片描述

redis-benchmark压力测试工具

redis-benchmark是Redis自带的性能测试工具

其参数如下

-h <hostname> 
服务器的主机名(默认值为127.0.0.1)。

-p <port> 
服务器的端口号(默认值为6379)。

-s <socket> 
服务器的套接字(会覆盖主机名和端口号)。

-a <password> 
登录Redis时进行身份验证的密码。

-c <clients> 
并发的连接数量(默认值为50)。

-n <requests> 
发出的请求总数(默认值为100000)。

-d <size> 
SET/GET命令所操作的值的数据大小,以字节为单位(默认值为2)。

–dbnum <db> 
选择用于性能测试的数据库的编号(默认值为0)。

-k <boolean> 
1=保持连接;0=重新连接(默认值为1)。

-r <keyspacelen> 
SET/GET/INCR命令使用随机键,SADD命令使用随机值。通过这个选项,基准测试会将参数中的__rand_int__字符串替换为一个12位的整数,这个整数的取值范围从0到keyspacelen-1。每次执行一条命令的时候,用于替换的整数值都会改变。通过这个参数,默认的测试方案会在指定范围之内尝试命中随机键。

-P <numreq> 
使用管道机制处理<numreq>条Redis请求。默认值为1(不使用管道机制)。

-q 
静默测试,只显示QPS的值。

–csv 
将测试结果输出为CSV格式的文件。

-l 
循环测试。基准测试会永远运行下去。

-t <tests> 
基准测试只会运行列表中用逗号分隔的命令。测试命令的名称和结果输出产生的名称相同。

-I 
空闲模式。只会打开N个空闲的连接,然后等待。

Redis基本命令

Redis默认共有16个数据库,并且默认使用第0个数据库

  • select 2: 切换到第二个数据库
  • dbsize: 查看该数据库大小
  • set key value: 存KV键值对
  • get key: 根据key取value
  • exists key: 判断当前key是否存在
  • move key: 移除当前key
  • expire key time: 设置key的存活时间,time是数字,以秒为单位
  • ttl key: 查看key的剩余时间
  • type key: 查看key的类型
  • keys *: 查看到所有的key
  • flushdb: 清空当前数据库
  • flushall: 清空所有数据库

Redis五大数据类型

String

set命令默认创建String类型

  • set key value: 设置键值对

    这个值可以设置成json,相当于设置了一个对象,如

    set user:1 {name:fisher, age: 1}

  • get key: 获取key的值

  • DEL key [key …]: 删除指定key

  • append key value: 追加字符串

  • strlen key: 查看字符串长度

  • incr key: 字符串加一

  • decr key: 字符串减一

  • incrby key n: 字符串加n

  • decrby key n: 字符串减n

  • GETRANGE key start end: 截取字符串[key, end], start和end从0开始.-1代表字符串末尾

  • SETRANGE key offset value: 替换字符串,从offset开始,之后的value长度的字符替换为value

  • SETEX key seconds value: 添加键值对并设置存活时间

  • SETNX key value: 如果key不存在,则创建键值对,存在则不创建

  • MSET key value [key value …]: 批量创建键值对,每对键值对用空格隔开

    也可以批量设置一个对象的值:mset user:2:name zhang user:2:age 14,这只是类对象,取值时还需要一个一个取,而不能将user:2作为一个对象直接使用set取
    在这里插入图片描述
    在这里插入图片描述

  • MGET key [key …]: 批量获取key对应的value

  • MSETNX key value [key value …]: 批量创建坚持对,不存在则创建,这个是原子性的,要么一起成功,要么一起失败

  • getset key value: 获取key的值后设置这个key的值,如果key不存在就创建,key存在就覆盖

List

List分为左和右

基本命令

  • RPUSH key value [value …]: 在列表右边添加元素,如果列表不存在则创建
  • LPUSH key value [value …]: 在列表左边添加元素,如果列表不存在则创建
  • LRANGE key start stop: 查看列表中的值
  • LLEN key: 获得列表长度
  • RPOP key: 从列表右边开始删除一个元素
  • LPOP key: 从列表左边开始删除一个元素
  • LINDEX key index: 通过下标获得元素值
  • LREM key count value: 根据元素名移除元素,count表示移除的数量,如果count的值多于该元素实际存在的数量就全部移除
  • LTRIM key start stop: 截取指定元素,其余元素会被移除
  • LSET key index value: 修改指定位置的元素
  • LINSERT key BEFORE|AFTER pivot value: 在指定位置插入元素
  • RPOPLPUSH source destination: 将列表中右边的元素取出,放入另一个列表的左边

Set

基本命令

  • SADD key member [member …]: 向集合中添加元素
  • SMEMBERS key : 查看集合中所有元素
  • SISMEMBER key member: 判断某个集合中是否存在某个值
  • SCARD key : 查看集合的元素个数
  • SREM key member [member …]: 移除集合中指定的元素
  • SRANDMEMBER key [count]: 随机取出集合中的元素
  • SPOP key [count]: 随机移除集合中的元素
  • SMOVE source destination member: 将元素从一个集合移动到另一个集合
  • SDIFF key [key …]: 求多个集合的差集,以第一个集合为参考
  • SINTER key [key …]: 求多个集合的交集
  • SUNION key [key …]: 求多个集合的并集

Hash

基本命令

  • HSET key field value: 添加一个hash的键值对
  • HGET key field: 根据hash键查看值
  • HMSET key field value [field value …]: 批量添加键值对
  • HMGET key field [field …]: 批量根据field获取value
  • HGETALL key: 获取hash中所有的键值对
  • HDEL key field [field …]: 删除hash中的feild
  • HLEN key: 获取hash长度
  • HEXISTS key field: 判断hash中某字段是否存在
  • HKEYS key: 获取hash中的所有key
  • HVALS key: 获取hash中的所有value
  • HINCRBY key field increment: 将hash中的field增加指定值
  • HSETNX key field value: 不存在该field则创建

Zset(有序集合)

Zset是在Set的基础上,每一个元素附带一个值,使其能有效的进行排序和查找

基本命令

  • ZADD key [NX|XX] [CH] [INCR] score member [score member …]: 增加元素
  • ZREM key member [member …]: 删除元素
  • ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]: 将scores为min到max的元素从小到大排列,-inf代表负无穷,+inf代表正无穷,ZRANGEBYSCORE myzset -inf +inf withscores表示从小到大排序所有元素.
  • ZREVRANGE key start stop [WITHSCORES]: 倒序排列元素
  • ZCARD key: 获取元素个数
  • ZCOUNT key min max: 获取指定区间元素个数

三种特殊的数据类型

geospatial

geospatial是处理地理位置的数据类型,是对Zset的封装

  • GEOADD key longitude latitude member [longitude latitude member …]: 按纬度和经度添加元素,longitude是纬度,latitude是经度

  • GEOPOS key member [member …]: 获得元素的经纬度信息

  • GEODIST key member1 member2 [unit]: 获取两元素之间直线距离,unit是单位,可以是m(米)、km(千米)、mi(英里)、ft(英尺)

  • GEOHASH key member [member …]: 获得某元素的位置Geohash字符串,两元素位置越近,Geohash字符串越相似

  • GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]: 以指定经纬度为中心,找到某半径范围内的元素.

    • longitude: 纬度
    • longitude: 经度
    • radius: 半径
    • WITHCOORD: 显示元素的经纬度信息
    • WITHDIST: 显示元素距中心的距离
    • WITHHASH: 显示元素距中心的Geohash值
    • COUNT: 规定显示元素的个数

    示例: GEORADIUS city 110 30 500 km withdist withcoord withhash count 1

  • GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]: 以某元素为中心找到到某半径范围内的元素,参数与GEORADIUS相似

  • 查看与移除元素操作: 由于geospatial底层是Zset,因此查看与移除命令可以与Zset通用

Hyperloglog

Hyperloglog是Redis的一种基数统计算法,固定占用内存12KB

  • PFADD key element [element …]: 向集合中添加元素
  • PFCOUNT key [key …]: 统计集合的基数
  • PFMERGE destkey sourcekey [sourcekey …]: 合并多个集合(并集)

Bitmap

Bitmap(位图),利用二进制记录数据,适合记录只有两个状态的数据,如是否打卡、是否登录等

  • SETBIT key offset value: 存数据.offset相当于键,必须是整型,value相当于值
  • GETBIT key offset: 根据键获得value
  • BITCOUNT key [start end]: 统计位图中1的个数,可以设置起始位置

Redis的事务

事务的基本操作

  • multi: 开启事务
  • exec: 提交事务
  • discard: 取消事务

Redis中的事务具有的特性: 一次性、顺序性、排他性

Redis中事务不保证原子性,也就是说在Reids的事务中,一行命令执行失败并不一定引起所有命令都不执行.

Redis中事务出错会有两种情况:

  1. 命令错误: 也就是在未执行命令时,Redis已经检查出这行命令是不正确的,此时当你提交事务后,Redis是不予执行的
  2. 执行时出错: 也就是命令本身没有错误,Redis也就检查不出来错误,但是执行后会因为某些问题不能执行,此时Redis将跳过这行命令,但其余命令依旧执行.

Redis的乐观锁

Reids的watch命令可以监控某一个key,开启事务后,在修改某个被watch监控的key时,如果他的值此时被其他线程修改,那本次修改是不会被执行的.

当遇到这种情况时,可以先使用unwatch解除监控,再使用watch监控,这样watch监控的值就是最新的数据,然后进行修改.
[学习笔记]Redis数据库基础知识_第2张图片

Jedis的使用

  1. 导入包

    <dependency>
        <groupId>redis.clientsgroupId>
        <artifactId>jedisartifactId>
        <version>3.2.0version>
    dependency>
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>fastjsonartifactId>
        <version>1.2.62version>
    dependency>
    
  2. Jedis的使用: 相当于将Redis的命令转换成了方法,每一个命令都有对应的方法

    以事务为例演示Jedis的使用

    public static void main(String[] args) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("k1", "v1");
            jsonObject.put("k2", "b2");
            String s = jsonObject.toJSONString();//创建JSON字符串
    
            Jedis jedis = new Jedis("127.0.0.1", 6379);//建立Redis连接
    
            System.out.println(jedis.ping());
    
            Transaction multi = jedis.multi();//开启事务,事务的执行和取消要使用Transaction
            try {
                multi.set("rediskey", s);
                multi.set("rediskey2", s);
    //            int i = 1 / 0;
                multi.exec();//执行事务
            } catch (Exception e) {
                multi.discard();//取消事务
                e.printStackTrace();
            }finally {
                System.out.println(jedis.get("rediskey"));
                jedis.close();
            }
        }
    

整合Spring Boot

在Spring Boot 2.x之后,底层使用lettuce连接Redis.lettuce底层使用了netty,数据在多个线程中可以共享,因此不存在线程不安全问题

  1. pom

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-redisartifactId>
    dependency>
    
  2. yaml

    spring:
      redis:
        host: localhost
        port: 6379
    
  3. 测试:

    @Autowired
    private RedisTemplate redisTemplate;
    
    @Test
    void contextLoads() {
        RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
        connection.flushDb();
        
        redisTemplate.opsForValue().set("boot", "hello");
        redisTemplate.opsForValue().get("boot");
    }
    

    redisTemplate.opsForValue(): String的操作

    redisTemplate.opsForList(): List的操作
    redisTemplate.opsForSet(): Set的操作

    以下依次类推

    redisTemplate.opsForHash
    redisTemplate.opsForZSet
    redisTemplate.opsForGeo
    redisTemplate.opsForHyperLogLog

    RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();获得Redis连接,这个连接可以进行选择数据库、数据库清除、开启事务、添加监视器等

序列化问题

  1. 实体类的序列化

当通过SpringBoot将对象存储到Redis中时,要将对象进行序列化,Redis不然将不会识别出这个对象的类型而无法存储,会报出SerializationException异常

将类进行序列化就是让其实现Serializable接口即可

public class User implements Serializable {
    private String name;
    private Integer age;
}
  1. 序列化配置

此外,通常也要将key和value都进行序列化,否则通过Java代码存储到Redis的key会进行转码

分析源码可知,SpringBoot为我们提供的RedisTemplate没有过多的进行序列化,并且它的类型是,而key基本都是String类型
[学习笔记]Redis数据库基础知识_第3张图片
因此我们重写一个RedisTemplate,只需要将方法名写成redisTemplate,并注册进Spring中,就会优先使用自己写的RedisTemplate

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    RedisTemplate<String, Object> template = new RedisTemplate<String,Object>();
    template.setConnectionFactory(factory);
    // Json序列化配置
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(om);
    // String 的序列化
    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    // key采用String的序列化方式
    // hash的key也采用String的序列化方式
    template.setKeySerializer(stringRedisSerializer);
    // value序列化方式采用jackson
    template.setHashKeySerializer(stringRedisSerializer);
    template.setValueSerializer(jackson2JsonRedisSerializer);
    // hash的value序列化方式采用jackson
    template.setHashValueSerializer(jackson2JsonRedisSerializer);
    template.afterPropertiesSet();

    return template;
}

此时,进入Redis的key和value都会进行序列化,这时那个对象的序列化就显得没那么必要,因为这里已经配置了value的序列化

Redis的持久化

Redis是内存数据库,所有操作都是在内存中进行的,断电即失,一些有用的信息需要将其放入本地磁盘中,也就是持久化.

Redis共有两种持久化模式:

  • RDB(Redis DataBase)
  • AOF(Appenf Only File)

RDB

这是Redis的默认的持久化模式, RDB会按照一定的规则,在父进程中创建一个子进程根据现有的内容生成RDB文件,持久化到磁盘中

清空所有数据库(即flushall)或者服务器的关闭也会触发RDB持久化
[学习笔记]Redis数据库基础知识_第4张图片
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程
都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的。
这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那
RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
[学习笔记]Redis数据库基础知识_第5张图片
这里可以设置保存快照的规则,默认是900秒内有1次请求或300内有10次请求,或60秒内有10000次请求就会触发RDB的持久化
在这里插入图片描述
这里可以修改持久化的rdb文件名,这个文件默认保存在redis的bin目录下

AOF

以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作.
[学习笔记]Redis数据库基础知识_第6张图片
在这里插入图片描述
上图所示, ADF默认是关闭的,开启时将no改成yes在这里插入图片描述
上图是redis的aof文件名,也就是AOF持久化时产生的文件,这个文件记录了所有的操作
在这里插入图片描述
上图是AOF持久化的规则

  • always: 每次修改都会进行一次持久化
  • everysec: 每秒进行一次持久化
  • no: 不主动进行持久化,由操作系统自主同步数据
    在这里插入图片描述
    上图配置AOF重写的大小,和重写的比例.由于AOF只会不停追加记录,不删除记录,因此规定一个文件重写的大小,超出这个大小就进行文件的重写,防止这个文件过度膨胀.

Redis的发布订阅

Redis也可以进行简单的消息订阅和发布
[学习笔记]Redis数据库基础知识_第7张图片

  • SUBSCRIBE channel [channel …]: 订阅指定频道
  • PUBLISH channel message: 向某个频道发信息
  • UNSUBSCRIBE [channel [channel …]]: 退订指定频道

Redis集群

Redis支持主从模式的集群,遵循主从复制的原则.主节点将数据复制给从节点,主节点主要负责写数据,从节点只负责读数据.一般采用一主二从的结构.

搭建一个伪分布式用于测试

复制三个conf文件,并修改端口、pid文件名、log文件名、rdb文件名配置

当Redis以守护进程方式运行时,Redis默认会把pid写入pid文件中

port 6381

pidfile /var/run/redis_6381.pid

logfile "redis6381.log"

dbfilename dump6381.rdb

主从模式的配置

一个Redis服务默认是主机,输入INFO replication就可以看到当前Redis的角色等信息
[学习笔记]Redis数据库基础知识_第8张图片
通过SLAVEOF host port命令可以指定本Redis的主机
[学习笔记]Redis数据库基础知识_第9张图片
通过SLAVEOF no one命令,指定自己为主机.

以上用命令配置主从机并不是永久的,当Redis服务重启后,这些配置就会消失,如果想进行永久配置,可以修改配置文件
在这里插入图片描述
按上图所示,跟命令相同,只是写在了配置文件中.

将集群配置成主从模式后,每次数据的更新,主机都会发送给从机,从机也会将信息持久化.

从机只能进行读操作,不可以进行写操作的,主机读写都可以

当主机宕机后,余下的从机仍能正常运行,只不过仍然只能进行读操作.如果在主机恢复之前没有在剩下的从机中选出主机,那原来的主机恢复后依旧是主机.如果选出主机(可以手动使用命令SLAVEOF no one将从机设置为主机),那原来的主机虽然角色依旧是主机,但没有任何一台从机认为他是主机,可以把这个主机看作脱离集群的独立个体.

当从机宕机后,如果整个集群又进行了数据的更新,那从机重连之后,会及时更新这部分数据.这里有全量复制增量复制的概念.当从机连接主机后会给主机发出sync同步命令,主机接收到命令后会启动后台存盘进程,收集所有用于修改数据的指令集并执行一遍,生成数据文件发动给从机,从几会将这个文件存盘并加载到内存中,这就是全量复制.从机连接主机之后,主机会继续收集所有修改指令,并发送给从机,这就是增量复制.

哨兵模式的配置

哨兵模式就是在集群中设置哨兵,当Redis主机出现故障,哨兵会检测出来并切换主机.

哨兵是一个独立的进程,通过发送请求监控各Redis服务器是否正常.当主机宕机后,哨兵会通过选举机制在其余从机中选出一名从机配置成主机.然后通过发布订阅模式,通知其他从机修改配置,让他们切换主机.当原来的主机再次启动后,他会被哨兵察觉并自动将其设置成从机.

配置哨兵

  1. 新建哨兵配置文件sentinel.conf,并进行如下配置

    # sentinel monitor 自定义唯一标识 host port 1代表
    sentinel monitor mymaster 127.0.0.1 6379 1
    

    哨兵文件只配置主机即可,下面是上述配置的解释

    • sentinel和monitor固定的配置命令,表示指定主服务
    • mymaster是一个自定义的唯一标识符,标识主服务.
    • host和port是主服务的主机和端口
    • 1代表主服务宕机,通过选举机制选出下一位主机

    网上找的哨兵的全部配置文件

    # Example sentinel.conf
    # 哨兵sentinel实例运行的端口 默认26379\
    port 26379
    # 哨兵sentinel的工作目录
    dir /tmp
    
    # master-name可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
    # 哨兵sentinel监控的redis主节点的 ip port
    # quorum 配置多少个sentinel哨兵统一认为master主节点失联 那么这时客观上认为主节点失联了
    # sentinel monitor    
    sentinel monitor mymaster 127.0.0.1 6379 2
    # 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
    # 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
    # sentinel auth-pass  
    sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
    # 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
    # sentinel down-after-milliseconds  
    sentinel down-after-milliseconds mymaster 30000
    # 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
    # sentinel parallel-syncs  
    sentinel parallel-syncs mymaster 1
    # 故障转移的超时时间 failover-timeout 可以用在以下这些方面:
    #1. 同一个sentinel对同一个master两次failover之间的间隔时间。
    #2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
    #3.当想要取消一个正在进行的failover所需要的时间。
    #4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,
    slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
    # 默认三分钟
    # sentinel failover-timeout  
    sentinel failover-timeout mymaster 180000
    # SCRIPTS EXECUTION
    #配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
    #对于脚本的运行结果有以下规则:
    #若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
    #若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
    #如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
    #一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
    #通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
    #通知脚本
    # shell编程
    # sentinel notification-script  
    sentinel notification-script mymaster /var/redis/notify.sh
    # 客户端重新配置主节点参数脚本
    # 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
    # 以下参数将会在调用脚本时传给脚本:
    #       
    # 目前总是“failover”,
    # 是“leader”或者“observer”中的一个。
    # 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
    # 这个脚本应该是通用的,能被多次调用,不是针对性的。
    # sentinel client-reconfig-script  置!
    sentinel client-reconfig-script mymaster /var/redis/reconfig.sh # 一般都是由运维来配
    
  2. 启动哨兵

    哨兵就是redis-sentinel,使用命令redis-sentinel 哨兵conf文件启动

    启动之后,哨兵就会对Redis进行监控.

Redis的穿透、击穿和雪崩

穿透

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

解决方案:

  • 布隆过滤器

    对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力.

  • 缓存空对象

    当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源.

击穿

缓存击穿,是指一个key非常热点,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,持久层数据库压力瞬间增大,可能会造成宕机.

解决方案:

  • 热点永不过期:击穿就是key过期造成的,设置key永不过期就不会出现击穿问题,但可能会对内存空间带来挑战.
  • 加互斥锁: 保证对于每个key同时只有一个线程去查询后端服务.种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大.

雪崩

缓存雪崩,是指在某一个时间段,缓存集中过期失效(如Redis节点宕机,手动设置的缓存在某个时间失效等).原本从缓存中查询的数据全都大量落到持久层数据库中,导致存储层压力暴增,存储层宕机.

解决方案:

  • 配置Redis高可用
  • 服务降级限流
  • 数据预热: 在正式部署之前,先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

你可能感兴趣的:([学习笔记]Redis数据库基础知识)