Redis基础及集群介绍

1.1.1 Redis介绍
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
读写速度:
写入速度: 8.6万/秒
读取速度: 12万/秒
主要功能:数据库、缓存和消息中间件
1.2 Redis命令
1.2.1 String类型
命令 说明 案例
set 添加key-value set username admin
get 根据key获取数据 get username
strlen 获取key的长度 strlen key
exists 判断key是否存在 exists name
返回1存在 0不存在
del 删除redis中的key del key
Keys 用于查询符合条件的key keys * 查询redis中全部的key
keys n?me 使用占位符获取数据
keys nam* 获取nam开头的数据
mset 赋值多个key-value mset key1 value1 key2 value2 key3 value3
mget 获取多个key的值 mget key1 key2
append 对某个key的值进行追加 append key value
type 检查某个key的类型 type key
select 切换redis数据库 select 0-15 redis中共有16个数据库
flushdb 清空单个数据库 flushdb
flushall 清空全部数据库 flushall
incr 自动加1 incr key
decr 自动减1 decr key
incrby 指定数值添加 incrby 10
decrby 指定数值减 decrby 10
expire 指定key的生效时间 单位秒 expire key 20
key20秒后失效
pexpire 指定key的失效时间 单位毫秒 pexpire key 2000
key 2000毫秒后失效
ttl 检查key的剩余存活时间 ttl key
persist 撤销key的失效时间 persist key

2 Redis
2.1 Java整合redis
2.1.1 特点
一般采用hash用来保存对象信息.
2.1.2 命令
命令 说明 案例
hset 为对象添加数据 hset key field value
hget 获取对象的属性值 hget key field
hexists 判断对象的属性是否存在 HEXISTS key field
1表示存在 0表示不存在
hdel 删除hash中的属性 hdel user field [field …]
hgetall 获取hash全部元素和值 HGETALL key
hkyes 获取hash中的所有字段 HKEYS key
hlen 获取hash中所有属性的数量 hlen key
hmget 获取hash里面指定字段的值 hmget key field [field …]
hmset 为hash的多个字段设定值 hmset key field value [field value …]
hsetnx 设置hash的一个字段,只有当这个字段不存在时有效 HSETNX key field value
hstrlen 获取hash中指定key的长度 HSTRLEN key field
hvals 获取hash的所有值 HVALS user
2.1.3 API操作
2.2 List类型
2.2.1 说明
Redis中List集合类型采用双端循环列表的形式保存数据.
链表特点:读取速度慢,查询两端速度快,增删快,
数组特点:读取速度快,增删慢.
List集合类型中有2种常用的数据类型.1栈,2队列
栈特点:先进后出 保存数据的方向与取数据的方向相同.
队列特点:先进先出 保存数据的方向与取数据的方向相反.
易错点: 采用list类型取出数据后,数据是否还存在??? 取出数据后,数据将从队列中消失.
实际业务场景:一般采用list类型当做消息队列使用.
消息队列的作用:缓解后台服务器压力.

2.2.2 List集合命令
压栈,弹栈
命令 说明 案例
lpush 从队列的左边入队一个或多个元素 LPUSH key value [value …]
rpush 从队列的右边入队一个或多个元素 RPUSH key value [value …]
lpop 从队列的左端出队一个元素 LPOP key
rpop 从队列的右端出队一个元素 RPOP key
lpushx 当队列存在时从队列的左侧入队一个元素 LPUSHX key value
rpushx 当队列存在时从队列的右侧入队一个元素 RPUSHx key value
lrange 从列表中获取指定返回的元素 LRANGE key start stop
Lrange key 0 -1 获取全部队列的数据
lrem 从存于 key 的列表里移除前 count 次出现的值为 value 的元素。 这个 count 参数通过下面几种方式影响这个操作:
• count > 0: 从头往尾移除值为 value 的元素。
• count < 0: 从尾往头移除值为 value 的元素。
• count = 0: 移除所有值为 value 的元素。 LREM list -2 “hello” 会从存于 list 的列表里移除最后两个出现的 “hello”。
需要注意的是,如果list里没有存在key就会被当作空list处理,所以当 key 不存在的时候,这个命令会返回 0。
Lset 设置 index 位置的list元素的值为 value LSET key index value

2.3 Redis中事务控制
2.3.1 需求说明
有时可能同一个业务中多次操作redis.所以需要控制事务.
2.3.2 命令
命令 说明 案例
multi 标记一个事务开始 127.0.0.1:6379> MULTI
OK
exec 执行所有multi之后发的命令 127.0.0.1:6379> EXEC
OK
discard 丢弃所有multi之后发的命令
2.3.3 API操作
//测试Redis中的事务
@Test
public void testTx(){
Jedis jedis = new Jedis(“192.168.126.174”,6379);

	//开启事务Transaction transaction = jedis.multi();//数据操作transaction.set("1809","tomcat猫大战葫芦娃");//transaction.exec();transaction.discard();
}

2.4 缓存三大问题
2.4.1 缓存穿透
条件:访问一个不存在的数据
说明:当访问一个不存在的数据时,因为缓存中没有这个key,导致缓存形同虚设.最终访问后台数据库.但是数据库中没有该数据所以返回null.
隐患:如果有人恶意频繁查询一个不存在的数据,可能会导致数据库负载高导致宕机.
总结:业务系统访问一个不存在的数据,称之为缓存穿透.

2.4.2 缓存击穿
条件:当缓存key失效/过期/未命中时,高并发访问该key
说明:如果给一个key设定了失效时间,当key失效时有一万的并发请求访问这个key,这时缓存失效,所有的请求都会访问后台数据库.称之为缓存击穿.
场景:微博热点消息访问量很大,如果该缓存失效则会直接访问后台数据库,导致数据库负载过高.
2.4.3 缓存雪崩
前提:高并发访问,缓存命中较低或者失效时
说明:假设缓存都设定了失效时间,在同一时间内缓存大量失效.如果这时用户高并发访问.缓存命中率过低.导致全部的用户访问都会访问后台真实的数据库.
场景:在高并发条件下.缓存动态更新时

2.5 Redis分片技术
2.5.1 Redis内存如何扩容
一般redis内存大小设定时一般为512M-1024M,如果用户需要缓存的数据有3g?如何解决?.则可以通过redis分片技术实现内存扩容.

2.5.2 Redis搭建步骤

  1. 拷贝配置文件

2.修改端口号
分别修改6380/6381配置文件的端口号

3.启动三台redis

进入指定端口的客户端
redis-cli -p 6380

2.5.3 测试API
//通过程序链接redis分片
@Test
public void testShard(){
//定义多个redis
List shards = new ArrayList<>();
shards.add(new JedisShardInfo(“192.168.126.174”,6379));
shards.add(new JedisShardInfo(“192.168.126.174”,6380));
shards.add(new JedisShardInfo(“192.168.126.174”,6381));
ShardedJedis shardedJedis =
new ShardedJedis(shards);
shardedJedis.set(“shards”,“redis分片技术”);
System.out.println(shardedJedis.get(“shards”));

}

2.5.4 分片链接池
//通过程序链接redis分片
@Test
public void testShard(){
//定义链接池
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(1000);
poolConfig.setMaxIdle(50);//最大的空闲数量
poolConfig.setMinIdle(10);//定义最小空闲链接数量
//定义多个redis
List shards = new ArrayList<>();
shards.add(new JedisShardInfo(“192.168.126.174”,6379));
shards.add(new JedisShardInfo(“192.168.126.174”,6380));
shards.add(new JedisShardInfo(“192.168.126.174”,6381));
ShardedJedisPool pool =
new ShardedJedisPool(poolConfig, shards);
ShardedJedis shardedJedis = pool.getResource();
shardedJedis.set(“shards”,“redis分片技术”);
System.out.println(shardedJedis.get(“shards”));
pool.returnResource(shardedJedis);
}
2.6 Hash一致性算法
2.6.1 介绍
一致性哈希算法在1997年由麻省理工学院提出(参见扩展阅读[1]),设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似。一致性哈希修正了CARP使用的简单哈希算法带来的问题,使得DHT可以在P2P环境中真正得到应用。
主要解决:数据一致性问题.

2.6.2 均衡性
说明:尽可能让节点中的数据均衡.引入虚拟节点概念,平衡数据.

2.6.3 单调性
说明:新增节点后,数据可以实现自动的迁移.

2.6.4 分散性
说明:因为分布式部署,导致项目不能够使用全部的内存空间.导致一个key有多个位置.
2.6.5 负载
说明:负载是从另一个角度考虑分散性.导致一个位置,有多个key.
好的哈希一致性算法,要求尽可能的降低分散性和负载.
优化:尽量让项目使用全部的内存空间.
2.7 Spring容器整合Redis分片
2.7.1 编辑pro文件
编辑redis.properties配置文件
redis.host=192.168.126.174
redis.port1=6379
redis.port2=6380
redis.port3=6381
redis.MaxTotal=1000
redis.MaxIdle=50
redis.MinIdle=10
2.7.2 编辑Spring配置文件





<!--2.定义分片节点对象  -->
<bean id="info1" class="redis.clients.jedis.JedisShardInfo"><constructor-arg name="host" value="${redis.host}"/><constructor-arg name="port" value="${redis.port1}"/>
</bean><bean id="info2" class="redis.clients.jedis.JedisShardInfo"><constructor-arg name="host" value="${redis.host}"/><constructor-arg name="port" value="${redis.port2}"/>
</bean><bean id="info3" class="redis.clients.jedis.JedisShardInfo"><constructor-arg name="host" value="${redis.host}"/><constructor-arg name="port" value="${redis.port3}"/>
</bean><!--3.定义分片的池对象  -->
<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool"><constructor-arg name="poolConfig" ref="poolConfig"/><constructor-arg name="shards"><list><ref bean="info1"/><ref bean="info2"/><ref bean="info3"/></list></constructor-arg>
</bean>

2.7.3 编辑工具类方法
@Service
public class RedisService {

//初始化时不会为属性赋值,当程序调用时,才会自动赋值.
@Autowired(required=false)
private ShardedJedisPool shardedJedisPool;//实现分片set操作
public void set(String key,String value){ShardedJedis jedis = shardedJedisPool.getResource();jedis.set(key, value);shardedJedisPool.returnResource(jedis);
}//实现分片get操作
public String get(String key){ShardedJedis jedis = shardedJedisPool.getResource();String result = jedis.get(key);shardedJedisPool.returnResource(jedis);return result;
}//自己扩展一个添加超时时间的方法

}

编辑完工具类后,将项目打包

2.7.4 实现业务调用

切换工具类方法:

3 Redis高级-hash
3.1 Redis-hash一致性
前提:由于分布式原因.导致程序不能使用全部内存空间.
3.1.1 分散性

3.1.2 负载

解决方案:尽可能的使用全部的内存空间.有效的减低分散性和负载.

4 Redis持久化策略
4.1 问题描述
Redis中的数据都保存内存中.内存中的数据,出现意外时,内存数据都会清空.如何保证redis中数据安全呢??
4.2 持久化具体分类
4.2.1 RDB模式
说明:该模式是redis中默认的持久化策略.
手动命令:
save : 立即执行持久化操作.其他的操作都会陷入阻塞.
bgsave : 在后台运行,不会让其他操作陷入阻塞.

4.2.1.1 特点:

  1. 持久化的效率最高,记录内存快照,每次保存都是最新的数据
  2. RDB模式占用空间小
  3. RDB模式保存数据是加密的.

4.2.1.2 内存策略:
save 900 1 在900秒内,有一个set操作,则持久化一次.
save 300 10 在300秒内.执行10次set操作,则持久化一次
save 60 10000 在60秒内,执行10000次set操作,则持久化一次

4.2.1.3 持久化文件保存路径

持久化文件保存路径.如果有需要进行手动的修改.

4.2.2 AOF模式
说明:AOF模式是将用户的全部操作过程,写入文件中.默认是关闭的.如果需要启动.则修改特定的配置文件.

启动策略:

4.2.2.1 持久化策略
appendfsync always 当用户执行一次set操作,则持久化一次
appendfsync everysec 每秒执行一次持久化
appendfsync no 由操作系统设定.(一般不用)

4.2.2.2 文件保存位置

4.2.3 AOF与RDB区别

  1. 用户默认使用RDB模式,如果开启AOF模式则使用AOF
  2. RDB模式的效率,高于AOF模式.
  3. RDB模式记录的是内存的快照.AOF模式记录用户全部的操作过程.
  4. 备份策略不同:
    RDB模式定期备份. 可能会造成数据丢失.
    AOF模式可以实现数据的实时备份. 但是效率较低.
  5. RDB模式占用磁盘空间小.恢复数据的时间短.
    AOF模式占用磁盘空间大,恢复数据的时间长
  6. RDB模式备份加密的
    AOF模式备份明码保存.
    5 Redis内存策略
    5.1.1 需求
    Redis中数据都保存在内存中,如果内存的小大不维护.则长时间的set操作,则内存肯定会溢出.如何处理??
    5.1.2 LRU算法
    内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做LRU,操作系统会根据哪些数据属于LRU而将其移出内存而腾出空间来加载另外的数据。
    5.1.3 内存策略
  7. volatile-lru 设定了超时时间的数据,采用LRU算法.
  8. allkeys-lru 所有的key中使用lru算法
  9. volatile-random 设定了超时时间的随机删除
  10. allkeys-random 所有key的随机删除
  11. volatile-ttl 将要过期的数据,提前删除.
  12. Noeviction 不会删除数据,但是会返回错误消息.
  13. Note 由操作系统负责维护.

内存策略修改. 560行

5.1.4 关于持久化实际案例
问题:根据分片知识,数据应该保存到不同的节点中,每个节点保存的数据应该是不同的.如果出现节点中的数据一致了,问:为什么???

问题说明:

图上所示:三个redis的节点公用一个rdb文件.当redis在启动时.根据配置文件中的持久化方式,加载对应的持久化文件.恢复内存数据.但是3个节点的持久化文件相同.则恢复的内存数据相同.
解决方案:每个节点配置文件中,对应不同的持久化文件.

6 Redis实现高可用
6.1 Redis主从结构
6.1.1 Redis分片中存在问题
说明:

  1. 如果分片中的一个节点宕机,将会影响整个服务.

  2. 采用分片技术,可能会出现数据负载不均现象.

  3. Redis分片没有数据的备份.
    6.1.2 结构划分
    1.6379主 6380 6381从机
    6.1.3 配置3台主机

  4. 复制文件
    cp -r shards sentinel

  5. 修改持久化文件名称
    分别修改3个持久化文件中名称.保证名称不一致即可.

    将配置文件修改好之后,启动服务器.

6.1.4 配置主从

  1. 检查当前节点的状态
    info replication

发现默认的条件下,redis节点都是主机.
2. 执行挂载命令

	将6381挂载到6379,当6379的从机
  1. 主从测试
    在redis主机中set数据,检查从机中是否有同步数据.
    6.2 哨兵实现高可用
    6.2.1 调用原理

6.2.2 配置哨兵

  1. 复制哨兵的文件
    cp sentinel.conf sentinel/

  2. 关闭保护模式

  3. 编辑监控主机的信息
    sentinel monitor mymaster 127.0.0.1 6379 2
    mymaster:代表当前主机信息 ip:端口
    2: 哨兵投票的票数

  4. 修改推选时间 改为10秒

  5. 修改推选超时时间

6.2.3 哨兵高可用测试

  1. 启动命令:
    redis-sentinel sentinel.conf

    通过日志可以看出,redis主机是6379
    
  2. 将6379节点宕机.检查redis哨兵是否会自动推选.

日志发现,哨兵选择6380为主机.
6.3 多个哨兵实现redis高可用
6.3.1 准备多个哨兵配置文件
说明:将原有哨兵复制三份.名称分别为sentinel-6379.conf/sentinel-6380.conf/sentinel-6381.conf

6.3.2 修改哨兵配置文件
1.修改哨兵的端口

2.修改序列号

  1. 修改选举票数

6.3.3 多个哨兵测试
分别启动多台哨兵.检查哨兵的状态.将redis主机宕机后,检查哨兵是否自动推选.程序是否正确.

6.3.4 哨兵搭建策略

  1. 先配置主从结构
    主从结构搭建完成后,可以实现自动的数据同步.并且维护各自的持久化文件.

  2. 编辑单台哨兵的配置文件

  3. 扩展多台哨兵.
    6.3.5 哨兵的优点

  4. 可以实现redis的高可用.

  5. 对应调用者可以通过哨兵链接当前主机.
    6.4 Spring整合哨兵
    6.4.1 入门案例
    //实现哨兵的测试
    @Test
    public void testSentinel(){
    //1.定义池
    JedisPoolConfig poolConfig = new JedisPoolConfig();
    poolConfig.setMaxTotal(1000);

    //2将redis哨兵节点写入集合
    Set<String> sentinels = new HashSet<>();
    sentinels.add("192.168.126.174:26379");
    sentinels.add("192.168.126.174:26380");
    sentinels.add("192.168.126.174:26381");//3.定义链接池
    JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels, poolConfig);
    Jedis jedis = pool.getResource();
    jedis.set("1111", "1808班");
    System.out.println(jedis.get("1111"));
    pool.returnResource(jedis);
    

    }

6.4.2 编辑pro配置文件
redis.sentinelA=192.168.126.174:26379
redis.sentinelB=192.168.126.174:26380
redis.sentinelC=192.168.126.174:26381
redis.MaxTotal=1000
redis.MaxIdle=50
redis.MinIdle=10
6.4.3 编辑Spring配置文件

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"><property name="maxTotal" value="${redis.MaxTotal}"/><property name="maxIdle"  value="${redis.MaxIdle}"/><property name="minIdle"  value="${redis.MinIdle}"/>
</bean><!--2.定义链接池  -->
<bean id="jedisSentinelPool" class="redis.clients.jedis.JedisSentinelPool"><constructor-arg  name="masterName" value="${redis.sentinel.master}"/><constructor-arg name="sentinels"><set><value>${redis.sentinelA}</value><value>${redis.sentinelB}</value><value>${redis.sentinelC}</value></set></constructor-arg><constructor-arg name="poolConfig" ref="poolConfig"/>
</bean>

6.4.4 编辑工具类
@Service
public class RedisService {

//由分片切换为哨兵
@Autowired(required=false)
private JedisSentinelPool jedisSentinelPool;public String get(String key){Jedis jedis = jedisSentinelPool.getResource();String result = jedis.get(key);jedisSentinelPool.returnResource(jedis);return result;
}public void set(String key,String value){Jedis jedis = jedisSentinelPool.getResource();jedis.set(key, value);jedisSentinelPool.returnResource(jedis);
}public void set(String key,String value,Integer seconds){Jedis jedis = jedisSentinelPool.getResource();//jedis.set(key, value);//jedis.expire(key, seconds); //设定超时时间jedis.setex(key, seconds, value);jedisSentinelPool.returnResource(jedis);
}
}

6.4.5 哨兵测试

6.4.6 哨兵和分片特点
分片:可以实现内存的动态的扩容.
哨兵:可以实现redis高可用.
集群:将分片和哨兵进行整合.

7 Redis集群搭建
7.1 集群规模划分
7.1.1 集群划分
说明:redis集群可以实现内存的动态扩容,redis节点的高可用.
规范:redis中主节点数量一般都是奇数个.
规模:3个主节点/6个从节点共9个redis节点. 7000-7008
7.2 搭建步骤
7.2.1 新建文件夹
mkdir 7000 7001 7002 7003 7004 7005 7006 7007 7008

7.2.2 拷贝配置文件
将redis根目录中的redis.conf文件,导入cluster/7000文件夹中.
cp redis.conf cluster/7000/
7.2.3 取消IP绑定

7.2.4 关闭保护模式

7.2.5 修改端口号

7.2.6 开启后台启动

7.2.7 修改PID文件路径

7.2.8 修改持久化文件路径

7.2.9 定义内存策略
560行

7.2.10 启动redis集群配置

7.2.11 添加集群配置文件

7.2.12 开启集群超时

7.2.13 复制多个配置文件

7.2.14 批量修改配置文件

7.2.15 Redis启动脚本

7.2.16 启动redis
检查redis节点启动是否正常.

7.2.17 搭建集群
说明:编辑ruby脚本命令
./src/redis-trib.rb create --replicas 2 192.168.126.174:7000 192.168.126.174:7001 192.168.126.174:7002 192.168.126.174:7003 192.168.126.174:7004 192.168.126.174:7005 192.168.126.174:7006 192.168.126.174:7007 192.168.126.174:7008

7.2.18 集群高可用测试
将7000主节点关闭.之后检查高可用是否正常.之后启动7000,检查7000是否为主节点的从.

7.2.19 错误解决
如果集群搭建有问题,则将除了redis.conf文件之外的文件都删除.之后关闭redis节点/重启.重新执行集群搭建指令.

7.2.20 Redis集群宕机条件
特点:集群中如果主机宕机,那么从机可以继续提供服务,
当主机中没有从机时,则向其它主机借用多余的从机.继续提供服务.如果主机宕机时没有从机可用,则集群崩溃.
答案:9个redis节点,节点宕机5-7次时集群才崩溃.
如图-25所示:

图- 25
7.2.21 Redis hash槽存储数据原理
说明: RedisCluster采用此分区,所有的键根据哈希函数(CRC16[key]&16383)映射到0-16384槽内,共16384个槽位,每个节点维护部分槽及槽所映射的键值数据.根据主节点的个数,均衡划分区间.
算法:哈希函数: Hash()=CRC16[key]&16384按位与
如图-26所示

图- 26

当向redis集群中插入数据时,首先将key进行计算.之后将计算结果匹配到具体的某一个槽的区间内,之后再将数据set到管理该槽的节点中.
如图-27所示

图- 27
7.2.22 Redis测试API
@Test
public void testCluster(){
Set nodes = new HashSet<>();
nodes.add(new HostAndPort(“192.168.126.174”, 7000));
nodes.add(new HostAndPort(“192.168.126.174”, 7001));
nodes.add(new HostAndPort(“192.168.126.174”, 7002));
nodes.add(new HostAndPort(“192.168.126.174”, 7003));
nodes.add(new HostAndPort(“192.168.126.174”, 7004));
nodes.add(new HostAndPort(“192.168.126.174”, 7005));
nodes.add(new HostAndPort(“192.168.126.174”, 7006));
nodes.add(new HostAndPort(“192.168.126.174”, 7007));
nodes.add(new HostAndPort(“192.168.126.174”, 7008));

	JedisCluster cluster = new JedisCluster(nodes);cluster.set("cc","集群测试");System.out.println(cluster.get("cc"));
}

Redis 是什么

面试官:你先来说下 Redis 是什么吧!

我:(这不就是总结下 Redis 的定义和特点嘛)Redis 是 C 语言开发的一个开源的(遵从 BSD 协议)高性能键值对(key-value)的内存数据库,可以用作数据库、缓存、消息中间件等。

它是一种 NoSQL(not-only sql,泛指非关系型数据库)的数据库。

我顿了一下,接着说,Redis 作为一个内存数据库:

性能优秀,数据在内存中,读写速度非常快,支持并发 10W QPS。单进程单线程,是线程安全的,采用 IO 多路复用机制。丰富的数据类型,支持字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。支持数据持久化。可以将内存中数据保存在磁盘中,重启时加载。主从复制,哨兵,高可用。可以用作分布式锁。可以作为消息中间件使用,支持发布订阅。

五种数据类型

面试官:总结的不错,看来是早有准备啊。刚来听你提到 Redis 支持五种数据类型,那你能简单说下这五种数据类型吗?

我:当然可以,但是在说之前,我觉得有必要先来了解下 Redis 内部内存管理是如何描述这 5 种数据类型的。

说着,我拿着笔给面试官画了一张图:

我:首先 Redis 内部使用一个 redisObject 对象来表示所有的 key 和 value。

redisObject 最主要的信息如上图所示:type 表示一个 value 对象具体是何种数据类型,encoding 是不同数据类型在 Redis 内部的存储方式。

比如:type=string 表示 value 存储的是一个普通字符串,那么 encoding 可以是 raw 或者 int。

我顿了一下,接着说,下面我简单说下 5 种数据类型:

①String 是 Redis 最基本的类型,可以理解成与 Memcached一模一样的类型,一个 Key 对应一个 Value。Value 不仅是 String,也可以是数字。

String 类型是二进制安全的,意思是 Redis 的 String 类型可以包含任何数据,比如 jpg 图片或者序列化的对象。String 类型的值最大能存储 512M。

②Hash是一个键值(key-value)的集合。Redis 的 Hash 是一个 String 的 Key 和 Value 的映射表,Hash 特别适合存储对象。常用命令:hget,hset,hgetall 等。

③List 列表是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或者尾部(右边) 常用命令:lpush、rpush、lpop、rpop、lrange(获取列表片段)等。

应用场景:List 应用场景非常多,也是 Redis 最重要的数据结构之一,比如 Twitter 的关注列表,粉丝列表都可以用 List 结构来实现。

数据结构:List 就是链表,可以用来当消息队列用。Redis 提供了 List 的 Push 和 Pop 操作,还提供了操作某一段的 API,可以直接查询或者删除某一段的元素。

实现方式:Redis List 的是实现是一个双向链表,既可以支持反向查找和遍历,更方便操作,不过带来了额外的内存开销。

④Set 是 String 类型的无序集合。集合是通过 hashtable 实现的。Set 中的元素是没有顺序的,而且是没有重复的。常用命令:sdd、spop、smembers、sunion 等。

应用场景:Redis Set 对外提供的功能和 List 一样是一个列表,特殊之处在于 Set 是自动去重的,而且 Set 提供了判断某个成员是否在一个 Set 集合中。

⑤Zset 和 Set 一样是 String 类型元素的集合,且不允许重复的元素。常用命令:zadd、zrange、zrem、zcard 等。

使用场景:Sorted Set 可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。

当你需要一个有序的并且不重复的集合列表,那么可以选择 Sorted Set 结构。

和 Set 相比,Sorted Set关联了一个 Double 类型权重的参数 Score,使得集合中的元素能够按照 Score 进行有序排列,Redis 正是通过分数来为集合中的成员进行从小到大的排序。

实现方式:Redis Sorted Set 的内部使用 HashMap 和跳跃表(skipList)来保证数据的存储和有序,HashMap 里放的是成员到 Score 的映射。

而跳跃表里存放的是所有的成员,排序依据是 HashMap 里存的 Score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。

数据类型应用场景总结:

面试官:想不到你平时也下了不少工夫,那 Redis 缓存你一定用过的吧?

我:用过的。

面试官:那你跟我说下你是怎么用的?

我是结合 Spring Boot 使用的。一般有两种方式,一种是直接通过 RedisTemplate 来使用,另一种是使用 Spring Cache 集成 Redis(也就是注解的方式)。

Redis 缓存

直接通过 RedisTemplate 来使用,使用 Spring Cache 集成 Redis pom.xml 中加入以下依赖:

org.springframework.bootspring-boot-starter-data-redisorg.apache.commonscommons-pool2org.springframework.bootspring-boot-starter-weborg.springframework.sessionspring-session-data-redisorg.projectlomboklomboktrueorg.springframework.bootspring-boot-starter-testtest

spring-boot-starter-data-redis:在 Spring Boot 2.x 以后底层不再使用 Jedis,而是换成了 Lettuce。

commons-pool2:用作 Redis 连接池,如不引入启动会报错。

spring-session-data-redis:Spring Session 引入,用作共享 Session。

配置文件 application.yml 的配置:

server: port: 8082 servlet: session: timeout: 30msspring:cache:type: redis redis: host: 127.0.0.1 port: 6379password:# redis默认情况下有16个分片,这里配置具体使用的分片,默认为0database: 0 lettuce: pool:# 连接池最大连接数(使用负数表示没有限制),默认8max-active: 100

创建实体类 User.java:

publicclassUserimplementsSerializable{privatestaticfinallong serialVersionUID = 662692455422902539L;private Integer id;private String name;private Integer age;publicUser(){ }publicUser(Integer id, String name, Integer age){this.id = id;this.name = name;this.age = age; }public Integer getId(){return id; }publicvoidsetId(Integer id){this.id = id; }public String getName(){return name; }publicvoidsetName(String name){this.name = name; }public Integer getAge(){return age; }publicvoidsetAge(Integer age){this.age = age; }@Overridepublic String toString(){return"User{" +“id=” + id +", name=’" + name + ‘’’ +", age=" + age +’}’; }}

RedisTemplate 的使用方式

默认情况下的模板只能支持 RedisTemplate<String, String>,也就是只能存入字符串,所以自定义模板很有必要。

添加配置类 RedisCacheConfig.java:

@Configuration@AutoConfigureAfter(RedisAutoConfiguration.class)publicclassRedisCacheConfig { @Beanpublic RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory connectionFactory) { RedisTemplate<String, Serializable> template = new RedisTemplate<>();template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new GenericJackson2JsonRedisSerializer());template.setConnectionFactory(connectionFactory);returntemplate; }}

测试类:

@RestController@RequestMapping("/user")publicclassUserController{public static Logger logger = LogManager.getLogger(UserController.class);@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate RedisTemplate<String, Serializable> redisCacheTemplate;@RequestMapping("/test")public void test() { redisCacheTemplate.opsForValue().set(“userkey”, new User(1, “张三”, 25)); User user = (User) redisCacheTemplate.opsForValue().get(“userkey”); logger.info(“当前获取对象:{}”, user.toString()); }

然后在浏览器访问,观察后台日志 http://localhost:8082/user/test

使用 Spring Cache 集成 Redis

Spring Cache 具备很好的灵活性,不仅能够使用 SPEL(spring expression language)来定义缓存的 Key 和各种 Condition,还提供了开箱即用的缓存临时存储方案,也支持和主流的专业缓存如 EhCache、Redis、Guava 的集成。

定义接口 UserService.java:

publicinterfaceUserService {User save(User user);voiddelete(int id);User get(Integer id);}

接口实现类 UserServiceImpl.java:

@ServicepublicclassUserServiceImplimplementsUserService{publicstatic Logger logger = LogManager.getLogger(UserServiceImpl.class);privatestatic Map<Integer, User> userMap = new HashMap<>();static { userMap.put(1, new User(1, “肖战”, 25)); userMap.put(2, new User(2, “王一博”, 26)); userMap.put(3, new User(3, “杨紫”, 24)); }@CachePut(value =“user”, key = “#user.id”)@Overridepublic User save(User user){ userMap.put(user.getId(), user); logger.info(“进入save方法,当前存储对象:{}”, user.toString());return user; }@CacheEvict(value=“user”, key = “#id”)@Overridepublicvoiddelete(int id){ userMap.remove(id); logger.info(“进入delete方法,删除成功”); }@Cacheable(value = “user”, key = “#id”)@Overridepublic User get(Integer id){ logger.info(“进入get方法,当前获取对象:{}”, userMap.get(id)==null?null:userMap.get(id).toString());return userMap.get(id); }}

为了方便演示数据库的操作,这里直接定义了一个 Map<Integer,User> userMap。

这里的核心是三个注解:

@Cachable@CachePut@CacheEvict

测试类:UserController

@RestController@RequestMapping("/user")publicclassUserController{publicstatic Logger logger = LogManager.getLogger(UserController.class);@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate RedisTemplate<String, Serializable> redisCacheTemplate;@Autowiredprivate UserService userService;@RequestMapping("/test")publicvoidtest(){ redisCacheTemplate.opsForValue().set(“userkey”, new User(1, “张三”, 25)); User user = (User) redisCacheTemplate.opsForValue().get(“userkey”); logger.info(“当前获取对象:{}”, user.toString()); }@RequestMapping("/add")publicvoidadd(){ User user = userService.save(new User(4, “李现”, 30)); logger.info(“添加的用户信息:{}”,user.toString()); }@RequestMapping("/delete")publicvoiddelete(){ userService.delete(4); }@RequestMapping("/get/{id}")publicvoidget(@PathVariable(“id”) String idStr) throws Exception{if (StringUtils.isBlank(idStr)) {thrownew Exception(“id为空”); } Integer id = Integer.parseInt(idStr); User user = userService.get(id); logger.info(“获取的用户信息:{}”,user.toString()); }}

用缓存要注意,启动类要加上一个注解开启缓存:

@SpringBootApplication(exclude=DataSourceAutoConfiguration.class)@EnableCachingpublicclassApplication{publicstaticvoidmain(String[] args){ SpringApplication.run(Application.class, args); }}

①先调用添加接口:http://localhost:8082/user/add

②再调用查询接口,查询 id=4 的用户信息:

可以看出,这里已经从缓存中获取数据了,因为上一步 add 方法已经把 id=4 的用户数据放入了 Redis 缓存 3、调用删除方法,删除 id=4 的用户信息,同时清除缓存:

④再次调用查询接口,查询 id=4 的用户信息:

没有了缓存,所以进入了 get 方法,从 userMap 中获取。

缓存注解

①@Cacheable

根据方法的请求参数对其结果进行缓存:

Key:缓存的 Key,可以为空,如果指定要按照 SPEL 表达式编写,如果不指定,则按照方法的所有参数进行组合。Value:缓存的名称,必须指定至少一个(如 @Cacheable (value=‘user’)或者 @Cacheable(value={‘user1’,‘user2’}))Condition:缓存的条件,可以为空,使用 SPEL 编写,返回 true 或者 false,只有为 true 才进行缓存。

②@CachePut

根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用。参数描述见上。

③@CacheEvict

根据条件对缓存进行清空:

Key:同上。Value:同上。Condition:同上。allEntries:是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存。beforeInvocation:是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存。缺省情况下,如果方法执行抛出异常,则不会清空缓存。

缓存问题

面试官:看了一下你的 Demo,简单易懂。那你在实际项目中使用缓存有遇到什么问题或者会遇到什么问题你知道吗?

我:缓存和数据库数据一致性问题:分布式环境下非常容易出现缓存和数据库间数据一致性问题,针对这一点,如果项目对缓存的要求是强一致性的,那么就不要使用缓存。

我们只能采取合适的策略来降低缓存和数据库间数据不一致的概率,而无法保证两者间的强一致性。

合适的策略包括合适的缓存更新策略,更新数据库后及时更新缓存、缓存失败时增加重试机制。

面试官:Redis 雪崩了解吗?

我:我了解的,目前电商首页以及热点数据都会去做缓存,一般缓存都是定时任务去刷新,或者查不到之后去更新缓存的,定时任务刷新就有一个问题。

举个栗子:如果首页所有 Key 的失效时间都是 12 小时,中午 12 点刷新的,我零点有个大促活动大量用户涌入,假设每秒 6000 个请求,本来缓存可以抗住每秒 5000 个请求,但是缓存中所有 Key 都失效了。

此时 6000 个/秒的请求全部落在了数据库上,数据库必然扛不住,真实情况可能 DBA 都没反应过来直接挂了。

此时,如果没什么特别的方案来处理,DBA 很着急,重启数据库,但是数据库立马又被新流量给打死了。这就是我理解的缓存雪崩。

我心想:同一时间大面积失效,瞬间 Redis 跟没有一样,那这个数量级别的请求直接打到数据库几乎是灾难性的。

你想想如果挂的是一个用户服务的库,那其他依赖他的库所有接口几乎都会报错。

如果没做熔断等策略基本上就是瞬间挂一片的节奏,你怎么重启用户都会把你打挂,等你重启好的时候,用户早睡觉去了,临睡之前,骂骂咧咧“什么垃圾产品”。

面试官摸摸了自己的头发:嗯,还不错,那这种情况你都是怎么应对的?

我:处理缓存雪崩简单,在批量往 Redis 存数据的时候,把每个 Key 的失效时间都加个随机值就好了,这样可以保证数据不会再同一时间大面积失效。

setRedis(key, value, time+Math.random()*10000);

如果 Redis 是集群部署,将热点数据均匀分布在不同的 Redis 库中也能避免全部失效。

或者设置热点数据永不过期,有更新操作就更新缓存就好了(比如运维更新了首页商品,那你刷下缓存就好了,不要设置过期时间),电商首页的数据也可以用这个操作,保险。

面试官:那你了解缓存穿透和击穿么,可以说说他们跟雪崩的区别吗?

我:嗯,了解,先说下缓存穿透吧,缓存穿透是指缓存和数据库中都没有的数据,而用户(黑客)不断发起请求。

举个栗子:我们数据库的 id 都是从 1 自增的,如果发起 id=-1 的数据或者 id 特别大不存在的数据,这样的不断攻击导致数据库压力很大,严重会击垮数据库。

我又接着说:至于缓存击穿嘛,这个跟缓存雪崩有点像,但是又有一点不一样,缓存雪崩是因为大面积的缓存失效,打崩了 DB。

而缓存击穿不同的是缓存击穿是指一个 Key 非常热点,在不停地扛着大量的请求,大并发集中对这一个点进行访问,当这个 Key 在失效的瞬间,持续的大并发直接落到了数据库上,就在这个 Key 的点上击穿了缓存。

面试官露出欣慰的眼光:那他们分别怎么解决?

我:缓存穿透我会在接口层增加校验,比如用户鉴权,参数做校验,不合法的校验直接 return,比如 id 做基础校验,id<=0 直接拦截。

面试官:那你还有别的方法吗?

我:我记得 Redis 里还有一个高级用法布隆过滤器(Bloom Filter)这个也能很好的预防缓存穿透的发生。

它的原理也很简单,就是利用高效的数据结构和算法快速判断出你这个 Key 是否在数据库中存在,不存在你 return 就好了,存在你就去查 DB 刷新 KV 再 return。

缓存击穿的话,设置热点数据永不过期,或者加上互斥锁就搞定了。作为暖男,代码给你准备好了,拿走不谢。

publicstatic String getData(String key)throws InterruptedException {//从Redis查询数据 String result = getDataByKV(key);//参数校验if (StringUtils.isBlank(result)) {try {//获得锁if (reenLock.tryLock()) {//去数据库查询 result = getDataByDB(key);//校验if (StringUtils.isNotBlank(result)) {//插进缓存 setDataToKV(key, result); } } else {//睡一会再拿 Thread.sleep(100L); result = getData(key); } } finally {//释放锁 reenLock.unlock(); } }return result; }

面试官:嗯嗯,还不错。

Redis 为何这么快

面试官:Redis 作为缓存大家都在用,那 Redis 一定很快咯?

我:当然了,官方提供的数据可以达到 100000+ 的 QPS(每秒内的查询次数),这个数据不比 Memcached 差!

面试官:Redis 这么快,它的“多线程模型”你了解吗?(露出邪魅一笑)

我:您是想问 Redis 这么快,为什么还是单线程的吧。Redis 确实是单进程单线程的模型,因为 Redis 完全是基于内存的操作,CPU 不是 Redis 的瓶颈,Redis 的瓶颈最有可能是机器内存的大小或者网络带宽。

既然单线程容易实现,而且 CPU 不会成为瓶颈,那就顺理成章的采用单线程的方案了(毕竟采用多线程会有很多麻烦)。

面试官:嗯,是的。那你能说说 Redis 是单线程的,为什么还能这么快吗?

我:可以这么说吧,总结一下有如下四点:

Redis 完全基于内存,绝大部分请求是纯粹的内存操作,非常迅速,数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度是 O(1)。数据结构简单,对数据操作也简单。采用单线程,避免了不必要的上下文切换和竞争条件,不存在多线程导致的 CPU 切换,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有死锁问题导致的性能消耗。使用多路复用 IO 模型,非阻塞 IO。

Redis 和 Memcached 的区别

面试官:嗯嗯,说的很详细。那你为什么选择 Redis 的缓存方案而不用 Memcached 呢?

我:原因有如下四点:

存储方式上:Memcache 会把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。Redis 有部分数据存在硬盘上,这样能保证数据的持久性。数据支持类型上:Memcache 对数据类型的支持简单,只支持简单的 key-value,,而 Redis 支持五种数据类型。使用底层模型不同:它们之间底层实现方式以及与客户端之间通信的应用协议不一样。Redis 直接自己构建了 VM 机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。Value 的大小:Redis 可以达到 1GB,而 Memcache 只有 1MB。

淘汰策略

面试官:那你说说你知道的 Redis 的淘汰策略有哪些?

我:Redis 有六种淘汰策略,如下图:

补充一下:Redis 4.0 加入了 LFU(least frequency use)淘汰策略,包括 volatile-lfu 和 allkeys-lfu,通过统计访问频率,将访问频率最少,即最不经常使用的 KV 淘汰。

持久化

面试官:你对 Redis 的持久化机制了解吗?能讲一下吗?

我:Redis 为了保证效率,数据缓存在了内存中,但是会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件中,以保证数据的持久化。

Redis 的持久化策略有两种:

RDB:快照形式是直接把内存中的数据保存到一个 dump 的文件中,定时保存,保存策略。AOF:把所有的对 Redis 的服务器进行修改的命令都存到一个文件里,命令的集合。Redis 默认是快照 RDB 的持久化方式。

当 Redis 重启的时候,它会优先使用 AOF 文件来还原数据集,因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。你甚至可以关闭持久化功能,让数据只在服务器运行时存。

面试官:那你再说下 RDB 是怎么工作的?

我:默认 Redis 是会以快照"RDB"的形式将数据持久化到磁盘的一个二进制文件 dump.rdb。

工作原理简单说一下:当 Redis 需要做持久化时,Redis 会 fork 一个子进程,子进程将数据写到磁盘上一个临时 RDB 文件中。

当子进程完成写临时文件后,将原来的 RDB 替换掉,这样的好处是可以 copy-on-write。

我:RDB 的优点是:这种文件非常适合用于备份:比如,你可以在最近的 24 小时内,每小时备份一次,并且在每个月的每一天也备份一个 RDB 文件。

这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。RDB 非常适合灾难恢复。

RDB 的缺点是:如果你需要尽量避免在服务器故障时丢失数据,那么RDB不合适你。

面试官:那你要不再说下 AOF?

我:(说就一起说下吧)使用 AOF 做持久化,每一个写命令都通过 write 函数追加到 appendonly.aof 中,配置方式如下:

appendfsyncyesappendfsync always #每次有数据修改发生时都会写入AOF文件。appendfsync everysec #每秒钟同步一次,该策略为AOF的缺省策略。

AOF 可以做到全程持久化,只需要在配置中开启 appendonly yes。这样 Redis 每执行一个修改数据的命令,都会把它添加到 AOF 文件中,当 Redis 重启时,将会读取 AOF 文件进行重放,恢复到 Redis 关闭前的最后时刻。

我顿了一下,继续说:使用 AOF 的优点是会让 Redis 变得非常耐久。可以设置不同的 Fsync 策略,AOF的默认策略是每秒钟 Fsync 一次,在这种配置下,就算发生故障停机,也最多丢失一秒钟的数据。

缺点是对于相同的数据集来说,AOF 的文件体积通常要大于 RDB 文件的体积。根据所使用的 Fsync 策略,AOF 的速度可能会慢于 RDB。

面试官又问:你说了这么多,那我该用哪一个呢?

我:如果你非常关心你的数据,但仍然可以承受数分钟内的数据丢失,那么可以额只使用 RDB 持久。

AOF 将 Redis 执行的每一条命令追加到磁盘中,处理巨大的写入会降低Redis的性能,不知道你是否可以接受。

数据库备份和灾难恢复:定时生成 RDB 快照非常便于进行数据库备份,并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度快。

当然了,Redis 支持同时开启 RDB 和 AOF,系统重启后,Redis 会优先使用 AOF 来恢复数据,这样丢失的数据会最少。

主从复制

面试官:Redis 单节点存在单点故障问题,为了解决单点问题,一般都需要对 Redis 配置从节点,然后使用哨兵来监听主节点的存活状态,如果主节点挂掉,从节点能继续提供缓存功能,你能说说 Redis 主从复制的过程和原理吗?

我有点懵,这个说来就话长了。但幸好提前准备了:主从配置结合哨兵模式能解决单点故障问题,提高 Redis 可用性。

从节点仅提供读操作,主节点提供写操作。对于读多写少的状况,可给主节点配置多个从节点,从而提高响应效率。

我顿了一下,接着说:关于复制过程,是这样的:

从节点执行 slaveof[masterIP][masterPort],保存主节点信息。从节点中的定时任务发现主节点信息,建立和主节点的 Socket 连接。从节点发送 Ping 信号,主节点返回 Pong,两边能互相通信。连接建立后,主节点将所有数据发送给从节点(数据同步)。主节点把当前的数据同步给从节点后,便完成了复制的建立过程。接下来,主节点就会持续的把写命令发送给从节点,保证主从数据一致性。

面试官:那你能详细说下数据同步的过程吗?

(我心想:这也问的太细了吧)我:可以。Redis 2.8 之前使用 sync[runId][offset] 同步命令,Redis 2.8 之后使用 psync[runId][offset] 命令。

两者不同在于,Sync 命令仅支持全量复制过程,Psync 支持全量和部分复制。

介绍同步之前,先介绍几个概念:

runId:每个 Redis 节点启动都会生成唯一的 uuid,每次 Redis 重启后,runId 都会发生变化。offset:主节点和从节点都各自维护自己的主从复制偏移量 offset,当主节点有写入命令时,offset=offset+命令的字节长度。从节点在收到主节点发送的命令后,也会增加自己的 offset,并把自己的 offset 发送给主节点。这样,主节点同时保存自己的 offset 和从节点的 offset,通过对比 offset 来判断主从节点数据是否一致。repl_backlog_size:保存在主节点上的一个固定长度的先进先出队列,默认大小是 1MB。

主节点发送数据给从节点过程中,主节点还会进行一些写操作,这时候的数据存储在复制缓冲区中。

从节点同步主节点数据完成后,主节点将缓冲区的数据继续发送给从节点,用于部分复制。

主节点响应写命令时,不但会把命名发送给从节点,还会写入复制积压缓冲区,用于复制命令丢失的数据补救。

上面是 Psync 的执行流程,从节点发送 psync[runId][offset] 命令,主节点有三种响应:

FULLRESYNC:第一次连接,进行全量复制CONTINUE:进行部分复制ERR:不支持 psync 命令,进行全量复制

面试官:很好,那你能具体说下全量复制和部分复制的过程吗?

我:可以!

上面是全量复制的流程。主要有以下几步:

从节点发送 psync ? -1 命令(因为第一次发送,不知道主节点的 runId,所以为?,因为是第一次复制,所以 offset=-1)。主节点发现从节点是第一次复制,返回 FULLRESYNC {runId} {offset},runId 是主节点的 runId,offset 是主节点目前的 offset。从节点接收主节点信息后,保存到 info 中。主节点在发送 FULLRESYNC 后,启动 bgsave 命令,生成 RDB 文件(数据持久化)。主节点发送 RDB 文件给从节点。到从节点加载数据完成这段期间主节点的写命令放入缓冲区。从节点清理自己的数据库数据。从节点加载 RDB 文件,将数据保存到自己的数据库中。如果从节点开启了 AOF,从节点会异步重写 AOF 文件。

关于部分复制有以下几点说明:

①部分复制主要是 Redis 针对全量复制的过高开销做出的一种优化措施,使用 psync[runId][offset] 命令实现。

当从节点正在复制主节点时,如果出现网络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,主节点的复制积压缓冲区将这部分数据直接发送给从节点。

这样就可以保持主从节点复制的一致性。补发的这部分数据一般远远小于全量数据。

②主从连接中断期间主节点依然响应命令,但因复制连接中断命令无法发送给从节点,不过主节点内的复制积压缓冲区依然可以保存最近一段时间的写命令数据。

③当主从连接恢复后,由于从节点之前保存了自身已复制的偏移量和主节点的运行 ID。因此会把它们当做 psync 参数发送给主节点,要求进行部分复制。

④主节点接收到 psync 命令后首先核对参数 runId 是否与自身一致,如果一致,说明之前复制的是当前主节点。

之后根据参数 offset 在复制积压缓冲区中查找,如果 offset 之后的数据存在,则对从节点发送+COUTINUE 命令,表示可以进行部分复制。因为缓冲区大小固定,若发生缓冲溢出,则进行全量复制。

⑤主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态。

哨兵

面试官:那主从复制会存在哪些问题呢?

我:主从复制会存在以下问题:

一旦主节点宕机,从节点晋升为主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预。主节点的写能力受到单机的限制。主节点的存储能力受到单机的限制。原生复制的弊端在早期的版本中也会比较突出,比如:Redis 复制中断后,从节点会发起 psync。此时如果同步不成功,则会进行全量同步,主库执行全量备份的同时,可能会造成毫秒或秒级的卡顿。

面试官:那比较主流的解决方案是什么呢?

我:当然是哨兵啊。

面试官:那么问题又来了。那你说下哨兵有哪些功能?

我:如图,是 Redis Sentinel(哨兵)的架构图。Redis Sentinel(哨兵)主要功能包括主节点存活检测、主从运行情况检测、自动故障转移、主从切换。

Redis Sentinel 最小配置是一主一从。Redis 的 Sentinel 系统可以用来管理多个 Redis 服务器。

该系统可以执行以下四个任务:

监控:不断检查主服务器和从服务器是否正常运行。通知:当被监控的某个 Redis 服务器出现问题,Sentinel 通过 API 脚本向管理员或者其他应用程序发出通知。自动故障转移:当主节点不能正常工作时,Sentinel 会开始一次自动的故障转移操作,它会将与失效主节点是主从关系的其中一个从节点升级为新的主节点,并且将其他的从节点指向新的主节点,这样人工干预就可以免了。配置提供者:在 Redis Sentinel 模式下,客户端应用在初始化时连接的是 Sentinel 节点集合,从中获取主节点的信息。

面试官:那你能说下哨兵的工作原理吗?

我:话不多说,直接上图:

①每个 Sentinel 节点都需要定期执行以下任务:每个 Sentinel 以每秒一次的频率,向它所知的主服务器、从服务器以及其他的 Sentinel 实例发送一个 PING 命令。(如上图)

②如果一个实例距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 所指定的值,那么这个实例会被 Sentinel 标记为主观下线。(如上图)

③如果一个主服务器被标记为主观下线,那么正在监视这个服务器的所有 Sentinel 节点,要以每秒一次的频率确认主服务器的确进入了主观下线状态。

④如果一个主服务器被标记为主观下线,并且有足够数量的 Sentinel(至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断,那么这个主服务器被标记为客观下线。

⑤一般情况下,每个 Sentinel 会以每 10 秒一次的频率向它已知的所有主服务器和从服务器发送 INFO 命令。

当一个主服务器被标记为客观下线时,Sentinel 向下线主服务器的所有从服务器发送 INFO 命令的频率,会从 10 秒一次改为每秒一次。

⑥Sentinel 和其他 Sentinel 协商客观下线的主节点的状态,如果处于 SDOWN 状态,则投票自动选出新的主节点,将剩余从节点指向新的主节点进行数据复制。

⑦当没有足够数量的 Sentinel 同意主服务器下线时,主服务器的客观下线状态就会被移除。

当主服务器重新向 Sentinel 的 PING 命令返回有效回复时,主服务器的主观下线状态就会被移除。

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. Python3 ID3决策树判断申请贷款是否成功

    目录1. 定义生成树2. 递归产生决策树3. 调用生成树4. 绘制决策树5. 调用函数 1. 定义生成树 # -*- coding: utf-8 -*- #生成树的函数from numpy import * import numpy as np import pandas as pd from math import log import operator # 计算数据集的信息熵(Information…...

    2024/5/3 11:10:48
  2. 11、数据结构与算法 - 二叉树 (一)基本概念

    二叉树1、二叉树的一些概念(1)、度结点拥有的子树数目成为结点的度(2)、层从跟开始定义,根为第1层,根的子结点为第2层,以此类推。(3)、高度树中结点的最大层次。根结点为最高。从下往上数(4)、深度同高度,从上往下2、树的5种形态(1)、满二叉树双亲结点都有2个子结…...

    2024/4/17 4:26:14
  3. Netty 简介

    很早以前其实就写过关于 Netty 的使用,最近发现在CSDN上一直有人在看很早写的 Netty 文章,个人感觉那时候写的很粗糙,怕影响同行的阅读质量,但是我也不知道为啥有这么多小伙伴关注Netty,所以决定重新写一些关于Netty的文章,补充以前的不足吧。 Netty能做啥 简单说就是用来…...

    2024/4/15 8:10:59
  4. J题 Jigglypuff(思维 + 记忆化搜索)

    文章目录题目思路队友敲的代码自己造的样例 题目思路 路径只要经过两次拆分和两次合并就是YES 因为长路径必定是由短路径构成的,将最短路径合并让自己处于尽可能左上的位置,这样是最贪心的,也是最优的。 所以找到图中所有的倾斜点对的合并点,再查看右下角矩阵内是否有合并点…...

    2024/4/17 4:26:06
  5. Python学习之路 | 爬虫篇【4】

    re模块 在Python中,通过内置的re模块提供对正则表达式的⽀持。正则表达式会被编译成⼀系列的字节码,然后由通过C编写的正则表达式引擎进⾏执⾏。 re模块⽀持下⾯的正则语法: 1 "." 2 "^" 3 "$" 4 "*" 5 "+" 6 "?&q…...

    2024/4/17 4:25:54
  6. 微机原理与接口技术四 存储系统

    SRAM芯片6264地址线:A0------A12; 数据线:D0------D7; 输出允许信号:OE; 写允许信号:WE; 选片信号:CS1,CS2。DRAM芯片2164A 2164A:64K1bit 采用行地址和列地址来确定一个单元; 行列地址分时传送,共用一组地址信号线; 地址信号线的数量仅为同等容量SRAM芯片的一半…...

    2024/4/17 4:25:42
  7. vue-项目部署到Nginx服务器

    vue项目开发完成之后 需要把代码部署到web服务器上,此处以Nginx为例找到你的项目目录,执行以下代码 npm run build 对vue项目进行打包,没有问题的话,会提示 Build complete.[root@izm5e331c21uktboqzfrvqz likang-demo]# npm run build> likang-demo@1.0.0 build /data…...

    2024/4/17 4:25:36
  8. Java项目高并发解决方案总结

    【高并发概述】1.怎么理解高并发?所谓高并发指的是:在同时或极短时间内,有大量的请求到达服务端,每个请求都需要服务端耗费资源进行处理,并做出相应的反馈。2.从服务端视角看高并发服务端处理请求需要耗费服务端的资源,比如能同时开启的进程数、能同时运行的线程数、网络…...

    2024/4/23 15:07:32
  9. Linux下的虚拟化部署 ---虚拟化下安装虚拟机、虚拟机管理命令、虚拟机在Linux系统中传输、虚拟机快照

    1.kvm虚拟化安装dnf group install "Virtualization Client" "Virtualization Hypervisor" "Virtualization Tools" -yVirtualization Client 虚拟化客户端Virtualization Tools …...

    2024/4/23 15:07:31
  10. learn_git详细学习记录

    1.直接进入沙盒 2. 本地操作相关篇节2.1 基础篇 2.2 处理复杂问题2.2.1 修改提交树2.3 杂项3. 远程操作相关篇章3.1 push && pull----git远程仓库 3.2 关于 origin 和它的周边 —— Git 远程仓库高级操作参考网站:learn_git 1.直接进入沙盒 在 URL 后头加上 ?NODEMO …...

    2024/4/23 15:07:24
  11. SpringMVC项目实现流程

    DispatcherServlet是前端控制器,是核心。 主要接口有:DispatcherServlet,ModeAndView,ViewResolve,Controller,HandlerMapping 1.用户在客户端向DispatcherServlet发送请求。 2.DispatcherServlet接受到请求后调用处理器映射器映射对应的Controller。 3.处理器映射器返回映射…...

    2024/4/23 15:07:23
  12. 二、三层交换机工作原理

    一、二层交换机 1、基本作用 交换机工作在二层,可以用来隔离冲突域,在OSI参考模型中,二层(数据链路层)的作用是寻址,这边寻址指的是MAC地址,而交换机就是对MAC地址进行转发,在每个交换机中,都有一张MAC地址表,这个表是交换机自动学习的,所以,总得来说交换机的作用是寻…...

    2024/4/23 15:07:22
  13. qrcodejs2生成二维码

    上图代码如下<!-- --> <template><div><div id="qrcode"></div></div> </template><script> import QRCode from qrcodejs2 export default {data () {return {}},mounted () {const qrcode = new QRCode(qrcode, …...

    2024/4/23 15:07:23
  14. Requests库03---发送请求(Cookie 和Session的区别)

    文章目录Cookie 和Session介绍Cookie 和Session区别Cookie 和Session作用获取响应中的Cookie注意会话对象 Cookie 和Session介绍都是数据,简单的可以理解为一种标识,当你访问某个网站时,会留下个人信息,而Cookie 和Session就是用来记录个人信息,判断你是否访问过此网站。C…...

    2024/4/23 15:07:21
  15. springboot使用maven插件搭建多profile环境

    作为一个程序员,不写博客是对不起自己的身份的,在平台记录一些平时使用的心得,大家一起交流,毕竟开源共享,一起交流嘛使用一个东西三问自己step1:是什么?多profile文件可以选择不同的maven实现打包step2:为什么?应对不同的环境使用不同的文件,不用重新打包,亦不用修…...

    2024/4/25 8:52:22
  16. Tarjan模板

    【题目描述】求有向图的强连通分量【输入格式】第一行两个正整数n,m(1<=n,m<=10000),分别表示点数及边数第二行到第m+1行,每行2个正整数u,v(1<=u,v<=n),表示1条有向边u→v【输出格式】共x行x表示强连通分量的个数。每行一组强连通分量格式:{元素1,元素2……...

    2024/5/5 2:44:47
  17. 这不明天就是520了!朋友非得让我宣传一下他,给了我几张照片。可惜我也不会什么PS,干脆直接用JS爆炸渲染一下吧!

    只有几张照片也挺枯涩的,我决定加了一首歌的部分片段 <audio src="aaa.mp3" autoplay="autoplay" ></audio>效果如下: 刚刚发现上传视频不支持本地,所以只能先这样了展示了。实现的代码如下 首先写个函数,实现boom类的定义: function bo…...

    2024/4/23 15:07:19
  18. 论文阅读:[2020CVPR]ROAM: Recurrently Optimizing Tracking Model(循环优化跟踪模型)

    论文阅读:ROAM: Recurrently Optimizing Tracking Model 论文链接:https://arxiv.org/abs/1907.12006 论文主体: 跟踪分为两个模块: 1)可调整大小以适应形状变化的跟踪模型:跟踪模型包含两个分支,其中响应生成分支通过预测置信度得分图来确定目标的存在,而bounding box…...

    2024/4/23 15:07:15
  19. 设计模式(刘伟)单例模式学习笔记

    单例模式导学模式动机模式定义单例模式结构模式分析一般情况下的代码实现单例模式实现代码客户端测试代码单例模式实现的过程中需要注意的三点单例模式实例之身份证号码类图身份证号码类代码辅助代码运行结果优点缺点适用环境模式应用拓展 导学你不能打开两个任务管理器,这就是…...

    2024/4/23 15:07:21
  20. MySQL表的四种分区类型

    一、什么是表分区 通俗地讲表分区是将一大表,根据条件分割成若干个小表。mysql5.1开始支持数据表分区了。 如:某用户表的记录超过了600万条,那么就可以根据入库日期将表分区,也可以根据所在地将表分区。当然也可根据其他的条件分区。 二、为什么要对表进行分区 为了改善大型…...

    2024/4/20 14:58:04

最新文章

  1. 物联网网关制造生产全流程揭秘!

    如果您正有开发和定制物联网网关的计划&#xff0c;找一个专业的物联网设备厂商协助您制造生产物联网网关可以节省大量时间和成本&#xff0c;可以让您能专注于当前核心业务&#xff0c;而无需将精力过多地投入到自己不擅长的领域。 当然&#xff0c;了解物联网网关的测试和制…...

    2024/5/10 5:24:00
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/9 21:23:04
  3. Go语言map、slice、channel底层实现(go面试)

    slice 切片是一个引用类型&#xff0c;其底层实现是一个结构体&#xff0c;包含以下字段&#xff1a; ptr&#xff1a;一个指向底层数组的指针&#xff0c;指针指向数组的第一个元素。 len&#xff1a;切片当前包含的元素数量。 cap&#xff1a;切片的容量&#xff0c;即底层…...

    2024/5/9 23:38:10
  4. audio_video_img图片音视频异步可视化加载

    最近在做即时消息&#xff0c;消息类型除了文字还有音频、视频、图片展示&#xff0c;如果消息很多&#xff0c;在切换聊天框时&#xff0c;会有明显卡顿&#xff0c;后续做了懒加载&#xff0c;方案是只加载用户能看到的资源&#xff0c;看不到的先不加载&#xff1b; LazyAud…...

    2024/5/8 2:36:28
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/8 6:01:22
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/9 15:10:32
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/9 4:20:59
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/7 11:36:39
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/6 1:40:42
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/8 20:48:49
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/7 9:26:26
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/8 19:33:07
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/8 20:38:49
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/9 7:32:17
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/9 17:11:10
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57