redis学习笔记

了解知识

1、Mecached(缓存)+mysql+垂直拆分(读写分离)

网站80%的情况都是在读,每次去查询数据库效率就会比较低!为减轻数据库的压力,我们可以使用缓存来保证压力;

发展过程:优化数据结构和索引---->文件缓存(IO)----->Memcached(当时最热门的技术)

 2、分库分表+水平拆分+mysql集群

MyISAM:表锁,十分影响效率!高并发十分影响效率

INNDB:行锁

慢慢的使用分库分表来解决写的压力。

 3、目前互联网架构

 4、为什么要用nosql?

用户的个人信息,社交网络,地理位置,用户数据爆发式增长;

5、nosql特点?

1、方便扩展

2、大数据高性能(redis一秒写8万次,读取11万次,nosql的缓存记录级,是一种细粒度的缓存,性能比较高)

3、数据库类型是多样性的(不需要事先设计数据库,随取随用)

4、传统的RDBMS和NOSQL

传统的RDBMS:

        结构化组织

         sql

         数据和关系都单纯的存在表中

        严格的一致性

        基础的事务

NOSQL:

        不仅仅是数据

        没有固定的查询语言

        键值对存储,列存储,文档存储,图形数据库

        最终一致性

        cap和base(异地多活)

        高性能、高可扩、高可用

6、Redis能干吗?

1、内存存储、持久化、内存是断电即失、所以说持久化很重要。

2、效率高,可用用于高速缓存。

3、发布订阅系统

4、地图信息分析

5、计时器、计数器。

7、Redis安装

1、下载解压 Download | Redis

2、进入解压后文件,可用看到redis的配置文件。

3、安装基本环境 yum install gcc-c++   make  make install

4、redis默认安装路径  /usr/local/bin

5、将redis配置文件复制一份

[root@localhost bin]# cp /opt/redis-6.2.7/redis.conf zxwconfig/

6、redis默认不是后台启动,要修改配置文件

 7、启动redis redis-server  zxwconfig/redis.conf     连接  redis-cli -p 6379

8、关闭命令  shutdown  exit

8、redis性能测试工具(redis-benchmark)

 

简单测试:测试 100个并发连接 10000个请求

redis-benchmark -h localhost -p 6379 -c 100 -n 10000

 分析参数

 10000个请求,100个并发,每次写入3个字节,只有一台服务器来处理这些请求, 所有请求在7.103毫秒处理完成,每秒处理56497.18个请求。

基础知识

1、redis默认有16个数据库,可以使用select 切换  select 3 切换至第三个

 

查看数据库所有key  keys*

清除当前数据库:flushdb

清除所有数据库:flushall

查看key是否存在:exist key

移除key:move key

设置key过期时间:expire key 10(10s过期)

查看key还有多长时间过期:ttl key

查看key的类型:type key

2、redis是单线程的

redis是基于内存操作的,所以CPU不是redis的性能瓶颈,redis的性能瓶颈是根据机器的内存和网络带宽决定的,既然可以使用单线程操作,就使用单线程了。

为什么redis单线程那么快?

误区1:高性能的服务器一定定多线程的

误区2:多线程(CPU上下文切换)一定比单线程效率高

核心:redis是将所有的数据全部放在内存中,所以说使用单线程去操作效率是最高的,多线程cpu上下文切换,是耗时的操作,对于内存来说,没有上下文切换效率就是最高的。

redis数据类型

String

拼接value值:append key "hello" (如果key不存在 则新建)

查看value长度:strlen key

value自增1:incr key(浏览量)

value自减1 :decr key

指定自增量:incrby key 10(自增10)

指定自减量:decr key 10

获取指定范围value:getrange key 0 3   getrange key 0  -1(查看所有)

替换value:setrange key 1 hello

setex key "hekkl" 30:设置值并且只有30秒有效时间;

setnx key "dkf" 30:不存在key才会设置,存在就会失败,不会覆盖

mset 一次设置多值:mset k1 v1 k2 v2 k3 v3;

mget一次获取多值:mget k1 k2 k3;

msetnx:mset k1 v1 k2 v2 (原子性操作,有一个失败则全部失败)

mset user:1:name zhangsan user:1:age 2(设置一个user:1对象为json字符串格式)

mget user:1:name user:1:age (获取对象对应的属性值)

getset key value 如果不存在值,则返回null,如果存在值则先返回原来值,再设置新值

 List(列表)

在redis里面可以吧list使用成栈 队列 阻塞队列

所有的list命令都是l开头;

lpush key value :设置值从左边放;rpush key value:设置值从右边放

lpop key 从左边移除值  rpop key 从右边移除值

lindex key 1:通过下标获取值

llen key:查看长度

lrem key 2 one :移除key中2个value为one的值;

ltrim key 1 2 :通过下标截取指定长度

rpoplpush:移除最后一个值并且添加到一个新的元素

lset key index value:更新指定下标的值,没有这个下标会报错

 llnsert key before value value;

 小结:

        list实际上是一个链表,left right都可以插入;

        如果key不存在,创建新的链表;

        如果key存在,新增内容;

        如果移除了所有值,空链表,也代表不存在;

        在两边插入值或者改动值则效率最高!中间元素则效率会低一点。

set(不可重复)

sadd key value:添加元素

smembers key:查看元素

sismember key value:查看元素是否存在,存在返回1 不存在返回0;

 scard key:获取元素的个数;

srem key value:移除元素;

srandmember key:随机获取key中的一个元素(可用于抽奖)

 spop key;随机删除一个set集合中的元素:

smove key key2 value(key中的元素)将一个指定的值,移动到另一个元素中;

 微博共同关注:

sdiff key1 key2;key1集合和key2元素的差集

sinter key1 key2:key1集合和key2元素的交集

sunion key1 key2:key1集合和key2元素的并集

 微博:A用户将所有关注的人放在一个set集合中,将他的粉丝以放在一个集合中;共同关注,共同爱好

Hash

hset key field value:放值

hget key field :取值

hmset key fileld value fileld value:放值多个

hget key field field:取值多个

hgetall key:取出所有值

 hdel key field:删除属性;

hlen key:查看长度

hexists key field:判断field是否存在

hkeys key:获取所有field;

hvals key:获取所有value;

hincrby key field:自增

 hsetnx key field value:如果存在则可以设置;

Zset(有序集合)

zadd:新增值

zrange key 0 -1:获取所有值

 zrangebyscare key -inf +inf:排序(从小到大)zrerange key 0 -1(从大到小)

 根据排序范围取值

 zrem key value:移除元素

 zcard key:获取有序集合个数

zcount key min max:获取指定区间元素的数量

 排行榜应用实现;

geospatial(地理位置)

添加geoadd

 获取:geopos

 geodist:m单位米 km单位千米 mi 单位英里 ft单位英尺

georadius:以给定的经纬度为中心,找出摸以半径内的元素;

我附近的人(获得附近所有人的定位,通过半径来查询);110 30 经纬度 半径10000km

 withdist :直线距离 withcoord:显示经纬度 count个数

 georadiusbymember 以哪座城市为中心 距离10000km的城市

 geohash:将二维的精度变成一维的字符串

 geo的底层实现原理就是zset 我们可以用zset命令来操作geo

Hyperloglog

redis hyerloglog 基数统计的算法;

优点:占用内存小。只需要12kb,2^64次方的数据。

网页的访问量(一个人访问一个网站多次,但还是算作一个人)

传统的方式,set保存用户的id,然后就可以统计set元素的数量作为判断标准,(set不重复)

这个方式如果保存大量的用户id,就会比较麻烦。

pfadd key value:放元素

pfcount key :统计元素,重复算一个;

 pfmerge mykey3 mykey mykey2:合并元素

 有0.81%的容错率

BitMaps(位存储)

使用bitmap来记录一周的打卡情况:

查看某一天是否打卡:

统计打卡天数

 事务

redis事务本质:一组命令的集合,一个事务中所有的命令都会被序列化,在事务执行的过程中,会按照顺序执行。

-----------队列 set set set 队列----------------

redis事务没有隔离级别的概念

所有的命令在事务中,并没有直接执行!只有发起执行命令的时候才会执行。

redis单条命令存在原子性,但是事务不保证原子性。

redis事务:开启事务(multi),命令入队,执行事务(exec)。

 discard取消事务;

编译型异常:(代码有问题,命令有错),事务中所有的命令都不会执行;

 运行时异常:如果事务队列中存在错误,那么其他命令是可以正常执行的

监控

悲观锁:认为什么时候都会出问题,无论做什么都会加锁。

乐观锁:认为什么时候都不会出问题,所以不会上锁,更新数据时候判断下,在此期间是否有人修改过这个数据

redis监控测试:

正常

 不正常:在事务执行入队期间,有别的线程修改了值

如何解决,先放弃锁,在监控  unwatch  watch money(放弃原来锁,获取最新的)

 Jedis

1.导包

<!--导入jedis包-->
    <dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.72</version>
        </dependency>
    </dependencies>

2.编码测试

第一步:注释#bind 127.0.0.1使其它物理机可以连接

第二步:关闭保护模式protected-mode no 

第三步:关闭防护墙

第四步:查看自己虚拟机地址;

public class TestPing {
    public static void main(String[] args) {
        Jedis redis=new Jedis("zxw.zxw.249.128",6379);
        System.out.println(redis.ping());
    }

}

事务

public class TestPing {
    public static void main(String[] args) {
        Jedis redis=new Jedis("zxw.zxw.249.128",6379);
        Transaction multi = redis.multi();
        JSONObject jsonObject=new JSONObject();
        jsonObject.put("hello","world");
        jsonObject.put("name","java");
        String result = jsonObject.toJSONString();
        try {
            multi.set("user1",result);
            multi.set("user2",result);
            multi.exec();
        } catch (Exception e) {
            multi.discard();//关闭事务
            e.printStackTrace();
        }finally {
            System.out.println(redis.get("user1"));
            System.out.println(redis.get("user2"));
            redis.close();
        }

    }

}

SpringBoot整合

 jedis:采用的直连,多个线程操作是不安全的

lettuce:采用netty,实例可以再多个线程进行共享,不存在线程不安全的情况;

源码分析:

@Bean
	@ConditionalOnMissingBean(name = "redisTemplate")//我们可以自定义一个redisTemple来替换这个默认的
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
		throws UnknownHostException {
        //默认的redisTemplate 没有过多的设置,redis对象都需要实例化
        //两个泛型都是object object的类型,我们使用后需要强制转换
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

	@Bean
	@ConditionalOnMissingBean //由于string类型是我们最常使用的一个类型,所以单独提出来一个
	public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
		throws UnknownHostException {
		StringRedisTemplate template = new StringRedisTemplate();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

整合测试

@SpringBootTest
class Redis02SpringbootApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test

    void contextLoads() {
        redisTemplate.opsForValue().set("name","江苏省连云港港");
        System.out.println(redisTemplate.opsForValue().get("name"));
    }

}

所有的对象需要序列化才能存入redis

@Component
@AllArgsConstructor
@NoArgsConstructor
@Data
//在企业中,我们的pojo层一般都会序列化
public class PoJo {
    private String user;
    private int age;
}
@SpringBootTest
class Redis02SpringbootApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test

    void contextLoads() {
        PoJo user=new PoJo("zs",20);
        redisTemplate.opsForValue().set("user",user);
        redisTemplate.opsForValue().get("user");
    }

}

不去序列化就会报错。

 编写自己的redisTemplate

package com.zxw.redis02springboot.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.net.UnknownHostException;

@Configuration
public class RedisConfig {
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        //我们为了自己开发方便,一般直接使用<String,Oject>
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(redisConnectionFactory);
        //json序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper=new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        //String方式的序列化
        StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
        //KEY采用string的方式序列化
        template.setKeySerializer(stringRedisSerializer);
        //hash采用string的方式序列化
        template.setHashKeySerializer(stringRedisSerializer);
        //value序列化采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //hash的value采用的序列化方式也是jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }
}

工作中一般用工具类开发;

Redis.Conf详解

单位:

1、配置文件 单位对大小不敏感;

2、可以包含其他配置文件

3、网络配置

bind 127..0.0.1(绑定ip)

protected-mode yes (保护模式)

port 6379(端口设置)

daemonize yes(已守护进程开启,默认no 需要改为yes)

pidfile /var/run/redis_6379.pid(如果已后台的方式运行,我们就需要一个pid文件)

# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice(日志)

logfile ""(日志文件名)

databases 16(默认数据库数量)

always-show-logo no(是否显示日志)

4、快照

持久化,在规定时间内,执行了多少次操作,则会持久化到文件。.rdb .aof

redis是内存数据库数据,如果没有持久化,那么数据断电即失

# save 3600 1        (3600秒至少有一个key进行修改,我们就进行持久化操作)
# save 300 100      (300秒有100key进行修改则会进行持久化)
# save 60 10000     (60秒内有10000key进行修改,则会进行持久化)

stop-writes-on-bgsave-error yes (持久化出错是否继续进行工作)

rdbcompression yes(是否压缩rdb文件,会消耗cpu资源)

rdbchecksum yes(保存rdf文件时,进行错误的校验)

dir ./  (rdb文件保存的目录)

requirepass 设置redis密码:命令config set requirepass

5、限制Clients

maxclients1000:设置能连接redis客户端的数量;

maxmemory:redis配置的最大内存容量;

maxmemory-policy noeviction:内存到达上限后的处理策略;

         1、volatile-lru:只对设置了过期时间的key进行LRU(默认值) 

        2、allkeys-lru : 删除lru算法的key   

        3、volatile-random:随机删除即将过期key   

        4、allkeys-random:随机删除   

        5、volatile-ttl : 删除即将过期的   

        6、noeviction : 永不过期,返回错误

6、Append only模式aof设置

appendonly no:默认是不开启aof,默认是rdb持久化;

appendfilename “appendonly.aof”:持久化文件的名称

appendsync everysec:每秒同步一次sysc

appendsync always:每次修改都会执行sysc,消耗性能;

appendsync no:不同步sync,这时候操作系统自己同步数据,速度最快;

Redis持久化

RDB

redis是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么服务器进程退出,服务器中的数据库状态也会消失,所以redis提供了持久化功能;

在指定时间间隔内将内存中的数据写入磁盘,也就是行话讲的snapshot快照,它恢复时是将快照文件直接读入内存。

redis会单独创建一个fork子线程来进行持久化,会将数据写入一个临时文件,待持久化过程结束了,再将这个文件替换上次持久化好的文件,整个过程中,主进程不需要任何的io操作,确保了极高的性能,如果需要大规模数据的恢复,且对于数据恢复的完整性不是很敏感,那么rdb要比aof更加高效,rdb缺点是最后一次持久化的文件可能丢失。rdb保存的文件名是dump.rdf

测试

1 改配置文件

 2 删除dump.rdf

 3 60s添加5个值

生成了一个rdb文件;

 触发rdb规则:
        1、save的规则满足情况,会自动触发rdb规则

        2、执行flush(flushdb flushall)会自动触发rdb规则

        3、退出redis,会自动触发rdb规则

如何恢复rdb文件:

        1;只需要将rdb文件放在redis的启动目录下,redis启动的时候就会检查dump.rdb文件,恢复其中数据;

        2、查看需要存放的位置;

 优点:

        1、适合大规模的数据恢复

        2、如果对数据完整性不高。

缺点:

        1、需要一定的时间间隔,如果redis意外宕机,最后一次修改数据就没有了

        2、fork进程时候,会占用内存空间。

AOF

 以日志的形式来记录每一个写操作,将redis执行过的所有指令都记录下来(读记录不操作),只许追加文件但不可以改写文件,redis启动之初就会读取该文件重构数据,就是redis重启就是根据日志文件将写指令从前往后都执行一遍来完成数据的恢复。

appendonly no:默认aof不开启

appendfsyc always:每次修改都会sysc 消耗性能

appendfsyc everysec :每秒执行一次,可能会丢失一秒数据;

appendfsyc no:不同步数据

开启后操作redis数据库,在redis目录下有appendonly.aof文件;

如果aof文件有错误,redis就会启动失败,需要用redis-check-aof  --fix   修复

 优点:

        1:每一次修改都同步,文件的完整性会更好

缺点:

        1:相对于数据文件来说,aof远远大于rdb,数据恢复也更慢;

        2:aof运行效率也慢,io操作,所以redis默认是rdb;

Redis发布订阅

Redis发布订阅是一种消息通信模式,发送者发送消息,订阅者接收消息。

PSUBSCRIBE pattern(订阅一个或者多个符合给定模式的频道)

PUBSUB subcommand (查看订阅与发布系统的状态)

PUBLISH channel message(将信息发布到指定的频道)

PUNSUBBCRIBE [pattern]退订所有给定模式的频道

SUBBSCRIBE channel:订阅给定的一个或多个频道的信息

UNSUBSCRIBE [channel]:指退订给定的频道

订阅端:

 发布者:

 使用场景:

        实时消息系统;实时聊天;订阅关注系统;

Redis主从复制

主从复制,是指将一台redis服务器的数据 ,复制到其它的redis服务器,前者称为主节点,后者称为从节点;数据的复制是单向的,只能由主节点到从节点,Master以写为主,Slave一读为主;

默认情况下,每台redis都是主节点;且一个主节点可以有多个从节点,但一个从节点只能有一个主节点;

主从复制的主要作用包括:

        1:数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式;

        2:故障恢复:当主节点出现问题时,可以用从节点提供服务,实现快速的故障恢复,实际上是一种服务的冗余;

        3:负载均衡:在主从复制的基础上,配合读写分离。可以由主节点提供写服务,从节点提供读服务;分担服务器均衡;尤其在写少读多的情况下,通过多个从节点分担负载,可以大大提高redis的并发量;

        4:高可用基石:出来上述作用之外,主从复制还是实现哨兵和集群的基础;

一般来说,要将redis运用于工程项目中,只用一台redis不能的,原因如下;

        1:从结构来看,单个redis服务器会1发生单点故障并且一台要接收所有的服务请求,压力比较大;

        2:从容量来说,单个redis容量有限,计算一台redis的内存容量为256g,也是不能全部用来存储redis数据的,一般来说,单个redis最大使用内存不应超过20g

环境配置

只配置从库,不要配置主库;

查看信息:info replication

 复制三份文件,修改以下配置

1:端口

2:pid名字

3:log文件名字

4:dump.rdb名字

 改完配置文件,查看是否正常启动

 一主二从

默认情况下,每台redis都是主节点,我们只需要配置从机就可以;

一主6379  二从 6380 6381

配置从机:slaveof 127.0.0.1 6379

 真实的主从配置应该是在配置文件中配置,那样才算是永久的,我们这里使用的是命令,是暂时的;

配置文件配置在从机中配置 主机ip 主机端口

 如果主机有密码。配置密码

读写分离

主机可以写,从机只能读不能写!主机中所有信息都会被从机保存

主机断开连接,从机依旧连接到主机,但是没有写操作了。这个时候。如果主机回来了,从机依然可以获得主机写的信息。

如果是使用命令行配置从机,从机宕机后重启就会变成主机;但只要变为从机,就会从主机中获取数据;

复制原理:

        slave启动成功连接到master后发送一个sync命令,master接收到命令后,启动后台的存盘进程,同时收集所有接收到的用于修改的数据集命令,在后台执行完毕后,master传送整个数据文件到slave,并一次性完成同步(全量复制);

        全量复制:将主机的数据全部传输给从机;

        增量复制;maste继续将新的收集到的修改命令传给slave,完成同步。

层层链路

 如果主机断开连接,我们可以使用SLAVEOF no one来让自己变为主机;

哨兵模式

哨兵模式是一种特殊的模式,redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程是独立运行,其原理是哨兵通过发送命令,等待redis的服务器响应,从而监控多个运行的redis实例,通过后台监控主机是否发送故障,如果故障了根据投票数自动的将从机转换为主机。

 哨兵的作用:

        1:通过发送命令,让redis服务器返回其运行状态,包括主机和从机;

        2:当哨兵检测到master宕机,会自动将slave转换为master,然后通过发布已订阅模式通知其他服务器修改配置文件;

然而一个哨兵对redis进行监控可能会出现问题,我们可以用多个哨兵进行监控,而且各个哨兵之间还可以进行监控;

假设主服务宕机,哨兵1先检测到这个结果,但是不会马上进行失效转移过程,仅仅是哨兵1认为这个服务不可用,称之为主观下线,当后面的哨兵也检测到服务不可以用,并且数量达到一定值时,会进行投票,投票的结果由一个哨兵发起,进行故障转移,切换成功后,就会通过发布订阅模式,让各个哨兵监控的从机实现切换主机了,这个过程叫客观下线;

 哨兵配置

配置文件:sentinel.conf  sentinel monitor 主机名称 ip 端口  1 哨兵进行投票决定谁当主机

 启动哨兵: redis-sentinel zxwconfig/sentinel.conf

 master断开,自动选择一个从机作为主机

 如果主机从新上线,就会变为从机

 哨兵模式优点:

        1:哨兵集群,基于主从复制模式,所有主从配置的优点,它都具有;

        2:主从可以切换,故障可以转移,系统可用性更好;

   哨兵模式缺点:

       1: redis不好在线扩容,几圈容量达到上限,在线扩容就很麻烦;

       2:实现哨兵模式的配置是很复杂的;

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

缓存穿透、击穿和雪崩

缓存穿透:

        是用户访问的数据既不在缓存当中,也不在数据库中。出于容错的考虑,如果从底层数据库查询不到数据,则不写入缓存。这就导致每次请求都会到底层数据库进行查询,缓存也失去了意义。当高并发或有人利用不存在的Key频繁攻击时,数据库的压力骤增,甚至崩溃,这就是缓存穿透问题。

解决方法:

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

        2:缓存空对象:当存储层不命中,返回空对象并将其缓存起来,同时设置一个过期时间,之后再访问这个数据从缓存中拿。存在问题:空值缓存起来也需要占用内存空间,没有太大意义并且设置过期时间也会导致和存储层时间窗口不一致,对保持数据一致性的业务会有影响;

缓存击穿:

如果缓存中的某个热点数据过期了,此时大量的请求访问了该热点数据,就无法从缓存中读取,直接访问数据库,数据库很容易就被高并发的请求冲垮,这就是缓存击穿

解决方法:

        1:设置热点数据不过期;

        2:加分布式锁:保证每一个key只有一个线程去访问,其它线程没有获得锁,只需要等待,这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大;

缓存雪崩:

大量的热点数据过期时间相同,导致数据在同一时刻集体失效。造成瞬时数据库请求量大、压力骤增,引起雪崩,导致数据库存在被打挂的风险。

解决方案:

        1:redis高可用:搭建集群,多搭几台redis

        2:限流降级:在缓存失效后,通过加锁或者队列来控制访问数据库的线程数量,比如对某个key同一时间只允许一个线程来访问。

        3:数据预热:在正式部署之前,把可能访问的数据先访问一遍,这样大部分数据就会存在缓存中,并且设置不同过期时间,让缓存失效的时间尽量均匀;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值