Redis是什么

  • 面试官:你先来说下redis是什么吧

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

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

五种数据类型

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

  • 我:当然可以,但是在说之前,我觉得有必要先来了解下Redis内部内存管理是如何描述这5种数据类型的。说着,我拿着笔给面试官画了一张图:

我:首先redis内部使用一个redisObject对象来表示所有的key和value,redisObject最主要的信息如上图所示:type表示一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式。比如:type=string表示value存储的是一个普通字符串,那么encoding可以是raw或者int。

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

1、string是redis最基本的类型,可以理解成与memcached一模一样的类型,一个key对应一个value。value不仅是string,也可以是数字。string类型是二进制安全的,意思是redis的string类型可以包含任何数据,比如jpg图片或者序列化的对象。string类型的值最大能存储512M。

2、Hash是一个键值(key-value)的集合。redis的hash是一个string的key和value的映射表,Hash特别适合存储对象。常用命令:hget,hset,hgetall等。

3、list列表是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或者尾部(右边) 常用命令:lpush、rpush、lpop、rpop、lrange(获取列表片段)等。应用场景:list应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表都可以用list结构来实现。数据结构:list就是链表,可以用来当消息队列用。redis提供了List的push和pop操作,还提供了操作某一段的api,可以直接查询或者删除某一段的元素。实现方式:redis list的是实现是一个双向链表,既可以支持反向查找和遍历,更方便操作,不过带来了额外的内存开销。

4、set是string类型的无序集合。集合是通过hashtable实现的。set中的元素是没有顺序的,而且是没有重复的。常用命令:sdd、spop、smembers、sunion等。应用场景:redis set对外提供的功能和list一样是一个列表,特殊之处在于set是自动去重的,而且set提供了判断某个成员是否在一个set集合中。

5、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(也就是注解的方式)。具体的代码我就不说了,在我的掘金中有一个demo(见下)。

Redis缓存

  • 直接通过RedisTemplate来使用

  • 使用spring cache集成Redis pom.xml中加入以下依赖:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>
  • 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: 8082servlet:session:timeout: 30ms
spring:cache:type: redisredis:host: 127.0.0.1port: 6379password:# redis默认情况下有16个分片,这里配置具体使用的分片,默认为0database: 0lettuce:pool:# 连接池最大连接数(使用负数表示没有限制),默认8max-active: 100

创建实体类User.java

public class User implements Serializable{private static final long serialVersionUID = 662692455422902539L;private Integer id;private String name;private Integer age;public User() {}public User(Integer id, String name, Integer age) {this.id = id;this.name = name;this.age = age;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(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)
public class RedisCacheConfig {@Beanpublic RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory connectionFactory) {RedisTemplate<String, Serializable> template = new RedisTemplate<>();template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new GenericJackson2JsonRedisSerializer());template.setConnectionFactory(connectionFactory);return template;}
}

测试类

@RestController
@RequestMapping("/user")
public class UserController {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

public interface UserService {User save(User user);void delete(int id);User get(Integer id);
}

接口实现类UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService{public static Logger logger = LogManager.getLogger(UserServiceImpl.class);private static 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")@Overridepublic void delete(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")
public class UserController {public static Logger logger = LogManager.getLogger(UserController.class);@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate RedisTemplate<String, Serializable> redisCacheTemplate;@Autowiredprivate UserService userService;@RequestMapping("/test")public void test() {redisCacheTemplate.opsForValue().set("userkey", new User(1, "张三", 25));User user = (User) redisCacheTemplate.opsForValue().get("userkey");logger.info("当前获取对象:{}", user.toString());}@RequestMapping("/add")public void add() {User user = userService.save(new User(4, "李现", 30));logger.info("添加的用户信息:{}",user.toString());}@RequestMapping("/delete")public void delete() {userService.delete(4);}@RequestMapping("/get/{id}")public void get(@PathVariable("id") String idStr) throws Exception{if (StringUtils.isBlank(idStr)) {throw new Exception("id为空");}Integer id = Integer.parseInt(idStr);User user = userService.get(id);logger.info("获取的用户信息:{}",user.toString());}
}

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

@SpringBootApplication(exclude=DataSourceAutoConfiguration.class)
@EnableCaching
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}

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

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

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

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

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

缓存注解

1、@Cacheable 根据方法的请求参数对其结果进行缓存

  • key:缓存的key,可以为空,如果指定要按照SPEL表达式编写,如果不指定,则按照方法的所有参数进行组合。

  • value:缓存的名称,必须指定至少一个(如 @Cacheable (value='user')或者@Cacheable(value={'user1','user2'}))

  • condition:缓存的条件,可以为空,使用SPEL编写,返回true或者false,只有为true才进行缓存。

2、@CachePut 根据方法的请求参数对其结果进行缓存,和@Cacheable不同的是,它每次都会触发真实方法的调用。参数描述见上。3、@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。缓存击穿的话,设置热点数据永不过期,或者加上互斥锁就搞定了。作为暖男,代码给你准备好了,拿走不谢。

public static 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呢

  • 我:

    • 1、存储方式上:memcache会把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。redis有部分数据存在硬盘上,这样能保证数据的持久性。

    • 2、数据支持类型上:memcache对数据类型的支持简单,只支持简单的key-value,,而redis支持五种数据类型。

    • 3、使用底层模型不同:它们之间底层实现方式以及与客户端之间通信的应用协议不一样。redis直接自己构建了VM机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

    • 4、value的大小:redis可以达到1GB,而memcache只有1MB。

淘汰策略

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

  • 我:Redis有六种淘汰策略

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

持久化

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

  • 我:redis为了保证效率,数据缓存在了内存中,但是会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件中,以保证数据的持久化。Redis的持久化策略有两种:1、RDB:快照形式是直接把内存中的数据保存到一个dump的文件中,定时保存,保存策略。2、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中,配置方式如下

appendfsync yes
appendfsync 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可用性。从节点仅提供读操作,主节点提供写操作。对于读多写少的状况,可给主节点配置多个从节点,从而提高响应效率。

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

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

  • (我心想:这也问的太细了吧)我:可以。redis2.8之前使用sync[runId][offset]同步命令,redis2.8之后使用psync[runId][offset]命令。两者不同在于,sync命令仅支持全量复制过程,psync支持全量和部分复制。介绍同步之前,先介绍几个概念:runId:每个redis节点启动都会生成唯一的uuid,每次redis重启后,runId都会发生变化。offset:主节点和从节点都各自维护自己的主从复制偏移量offset,当主节点有写入命令时,offset=offset+命令的字节长度。从节点在收到主节点发送的命令后,也会增加自己的offset,并把自己的offset发送给主节点。这样,主节点同时保存自己的offset和从节点的offset,通过对比offset来判断主从节点数据是否一致。repl_backlog_size:保存在主节点上的一个固定长度的先进先出队列,默认大小是1MB。(1)主节点发送数据给从节点过程中,主节点还会进行一些写操作,这时候的数据存储在复制缓冲区中。从节点同步主节点数据完成后,主节点将缓冲区的数据继续发送给从节点,用于部分复制。(2)主节点响应写命令时,不但会把命名发送给从节点,还会写入复制积压缓冲区,用于复制命令丢失的数据补救。

上面是psync的执行流程:从节点发送psync[runId][offset]命令,主节点有三种响应:(1)FULLRESYNC:第一次连接,进行全量复制 (2)CONTINUE:进行部分复制 (3)ERR:不支持psync命令,进行全量复制

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

  • 我:可以

关于部分复制有以下几点说明:1、部分复制主要是Redis针对全量复制的过高开销做出的一种优化措施,使用psync[runId][offset]命令实现。当从节点正在复制主节点时,如果出现网络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,主节点的复制积压缓冲区将这部分数据直接发送给从节点,这样就可以保持主从节点复制的一致性。补发的这部分数据一般远远小于全量数据。2、主从连接中断期间主节点依然响应命令,但因复制连接中断命令无法发送给从节点,不过主节点内的复制积压缓冲区依然可以保存最近一段时间的写命令数据。3、当主从连接恢复后,由于从节点之前保存了自身已复制的偏移量和主节点的运行ID。因此会把它们当做psync参数发送给主节点,要求进行部分复制。4、主节点接收到psync命令后首先核对参数runId是否与自身一致,如果一致,说明之前复制的是当前主节点;之后根据参数offset在复制积压缓冲区中查找,如果offset之后的数据存在,则对从节点发送+COUTINUE命令,表示可以进行部分复制。因为缓冲区大小固定,若发生缓冲溢出,则进行全量复制。5、主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态。

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

1、从节点发送psync ? -1命令(因为第一次发送,不知道主节点的runId,所以为?,因为是第一次复制,所以offset=-1)。

2、主节点发现从节点是第一次复制,返回FULLRESYNC {runId} {offset},runId是主节点的runId,offset是主节点目前的offset。

3、从节点接收主节点信息后,保存到info中。

4、主节点在发送FULLRESYNC后,启动bgsave命令,生成RDB文件(数据持久化)。

5、主节点发送RDB文件给从节点。到从节点加载数据完成这段期间主节点的写命令放入缓冲区。

6、从节点清理自己的数据库数据。

7、从节点加载RDB文件,将数据保存到自己的数据库中。

8、如果从节点开启了AOF,从节点会异步重写AOF文件。

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

1、部分复制主要是Redis针对全量复制的过高开销做出的一种优化措施,使用psync[runId][offset]命令实现。当从节点正在复制主节点时,如果出现网络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,主节点的复制积压缓冲区将这部分数据直接发送给从节点,这样就可以保持主从节点复制的一致性。补发的这部分数据一般远远小于全量数据。

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

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

4、主节点接收到psync命令后首先核对参数runId是否与自身一致,如果一致,说明之前复制的是当前主节点;之后根据参数offset在复制积压缓冲区中查找,如果offset之后的数据存在,则对从节点发送+COUTINUE命令,表示可以进行部分复制。因为缓冲区大小固定,若发生缓冲溢出,则进行全量复制。

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

哨兵

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

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

1、一旦主节点宕机,从节点晋升为主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预。

2、主节点的写能力受到单机的限制。

3、主节点的存储能力受到单机的限制。

4、原生复制的弊端在早期的版本中也会比较突出,比如:redis复制中断后,从节点会发起psync。此时如果同步不成功,则会进行全量同步,主库执行全量备份的同时,可能会造成毫秒或秒级的卡顿。

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

我:当然是哨兵啊。

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

我:如图,是Redis Sentinel(哨兵)的架构图。Redis Sentinel(哨兵)主要功能包括主节点存活检测、主从运行情况检测、自动故障转移、主从切换。Redis Sentinel最小配置是一主一从。Redis的Sentinel系统可以用来管理多个Redis服务器,该系统可以执行以下四个任务:

1、监控:不断检查主服务器和从服务器是否正常运行。

2、通知:当被监控的某个redis服务器出现问题,Sentinel通过API脚本向管理员或者其他应用程序发出通知。

3、自动故障转移:当主节点不能正常工作时,Sentinel会开始一次自动的故障转移操作,它会将与失效主节点是主从关系的其中一个从节点升级为新的主节点,并且将其他的从节点指向新的主节点,这样人工干预就可以免了。

4、配置提供者:在Redis Sentinel模式下,客户端应用在初始化时连接的是Sentinel节点集合,从中获取主节点的信息。

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

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

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

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

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

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

5、一般情况下,每个Sentinel会以每10秒一次的频率向它已知的所有主服务器和从服务器发送INFO命令,当一个主服务器被标记为客观下线时,Sentinel向下线主服务器的所有从服务器发送INFO命令的频率,会从10秒一次改为每秒一次。

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

7、当没有足够数量的Sentinel同意主服务器下线时,主服务器的客观下线状态就会被移除。当主服务器重新向Sentinel的PING命令返回有效回复时,主服务器的主观下线状态就会被移除。

总结

本文在一次面试的过程中讲述了Redis是什么,Redis的特点和功能,Redis缓存的使用,Redis为什么能这么快,Redis缓存的淘汰策略,持久化的两种方式,Redis高可用部分的主从复制和哨兵的基本原理。只要功夫深,铁杵磨成针,平时准备好,面试不用慌。虽然面试不一定是这样问的,但万变不离其“宗”。(笔者觉得这种问答形式的博客很不错,可读性强而且读后记的比较深刻

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

相关文章

  1. vmware安装Centos7.7报错:can‘t read superblock

    最近vmware安装Centos7.7碰到一个很少见的错误,估计没人有机会遇到我这样的错误,选择了安装以后报这样的错: mount: /dev/mapper/live-rw: can’t read superblock实际上这个报错没有任何意义,只是我的iso包不完整,在centos7.7系统里安装了vmware,然后又使用vmware安装ce…...

    2024/5/4 18:04:35
  2. 基于C++代码的UE4学习(四十五)——为坦克开火添加粒子系统

    需要用到UParticleSystemComponent。先在头文件中添加如下代码:1 UPROPERTY(EditAnywhere, BlueprintReadWrite) 2 class UParticleSystemComponent* fire;在源文件中添加如下代码:1 fire = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("…...

    2024/5/7 20:37:40
  3. 阿里研究员谷朴:警惕软件复杂度困局

    作者 | 张瓅玶(谷朴) 阿里巴巴研究员 **导读:**对于大型的软件系统如互联网分布式应用或企业级软件,为何我们常常会陷入复杂度陷阱?如何识别复杂度增长的因素?在代码开发以及演进的过程中需要遵循哪些原则?本文将分享阿里研究员谷朴关于软件复杂度的思考:什么是复杂度、…...

    2024/5/5 22:35:02
  4. Spring学习笔记01-IOC概念及简单使用

    spring初识 1、框架 ​ 框架就是一些类和接口的集合,通过这些类和接口协调来完成一系列的程序实现。JAVA框架可以分为三层:表示层,业务层和物理层。框架又叫做开发中的半成品,它不能提供整个WEB应用程序的所有东西,但是有了框架,我们就可以集中精力进行业务逻辑的开发而…...

    2024/5/8 13:25:12
  5. 超全面的后端开发C/C++面经整理分享含详细参考答案 包括简历分享

    本文为博主2020年秋招提前批的c/c++后端开发面经整理,包括C/C++语言基础,计网,数据库,linux,操作系统,场景题,智力题和hr常问题。面试问题来自前人的工作和博主面试时遇到的值得记录的问题,其中面试题答案多为博主自行解答(并且面试的时候也基本是这样回答的),回答中…...

    2024/5/8 7:53:27
  6. 关系型数据库与非关系型数据库

    前言 你是否在为系统的数据库来一波大流量就几乎打满CPU,日常CPU居高不下烦恼?你是否在各种NoSql间纠结不定,到底该选用那种最好?今天的你就是昨天的我,这也是写这篇文章的初衷。 作为互联网从业人员,我们要知道关系型数据库(MySql、Oracle)无法满足我们对存储的所有要…...

    2024/5/8 21:33:27
  7. 服务器ftp软件,服务器ftp软件下载文件配置其运行环境的办法

    ftp软件是一种文件传输下载方式,它是TCP/IP协议栈的一部分;其中FTP又由两部分组成,一部分是FTP的服务器,另一部分是FTP的客户端!它能够高效安全地进行文件传输下载操作!可以使用服务器管理工具来作为FTP的客户端,进行FTP的操作,实现FTP的下载安装。接下来介绍服务器ftp…...

    2024/5/8 14:37:59
  8. 基于C++代码的UE4学习(四十)——为玩家角色添加噪音

    之前在AI中添加了听觉功能,还需要在主角中添加噪音,本例中完成当玩家角色跳跃的时候,产生噪音,从而可以被AI听见。在Character头文件上加入以下代码。1 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Emitter) 2 class UPawnNoiseEmitterComponent* E…...

    2024/5/8 19:43:36
  9. decorator 装饰器

    许多面向对象都有decorator(装饰器)函数,比如python中也可以用decorator函数来强化代码,decorator相当于一个高阶函数,接收一个函数,返回一个被装饰后的函数。注: javascript中也有decorator相关的提案,只是目前node以及各浏览器中均不支持。只能通过安装babel插件来转换代…...

    2024/5/6 13:38:32
  10. 服务器ftp工具,盘点一款很好用的服务器ftp工具,附上教程

    ftp工具是一种文件传输下载方式,它是TCP/IP协议栈的一部分;其中FTP又由两部分组成,一部分是FTP的服务器,另一部分是FTP的客户端!它能够高效安全地进行文件传输下载操作!可以使用服务器管理工具来作为FTP的客户端,进行FTP的操作,实现FTP的下载安装。接下来介绍服务器ftp…...

    2024/4/23 6:43:08
  11. 简信CRM:企业如何实现私有化部署CRM?

    很多企业在使用CRM系统时,都考虑过部署模式的问题,目前市面上的部署模式可以分为两种,一种是SaaS部署模式,一种是独立部署模式。 对于在局域网中办公,或是比较重视企业内部数据安全的大型企业、政府机构,更适用于独立部署模式,具有灵活的扩展性,可实现更多个性化服务。…...

    2024/4/15 3:07:40
  12. 【计算机网络】网络层 : 路由算法 ( 路由算法分类 | 静态路由算法 | 动态路由算法 | 全局性动态路由算法 | 分散性动态路由算法 | 分层次路由选择协议 )

    文章目录一、路由算法二、路由算法 分类三、静态路由算法四、动态路由算法五、动态路由算法 分类六、分层次的路由选择协议一、路由算法路由算法 : 选择数传输的 “最佳路由” , 该 “最佳” 是相对于某特定要求得出的合理选择 ;路由表 : 又称为 转发表 , 有如下条目 :目的网络…...

    2024/5/8 15:41:18
  13. nginx入门手记

    nginx入门篇1、centos安装nginx1.1 创建nginx用户,安装所需依赖(root用户)1.2安装nginx(一般用户,没给sudo权限)1.3极简配置1.3.1nginx.conf1.3.2 vhost /wwyft.cn.conf 配置文件示例2、HELLO NGINX(以echo模块为例,记录加装模块的方法)3、nginx反向代理入门3.1 locat…...

    2024/4/24 5:23:01
  14. 5G智慧医疗十大应用场景?道翰天琼认知智能机器人平台API接口大脑为您揭秘-2。

    都说5G会改变千行百业,其中,5G医疗健康就是5G技术在医疗健康行业的一个重要应用领域。随着 5G 正式商用的到来以及与大数据、互联网+、人工智能、区块链等前沿技术的充分整合和运用, 5G 医疗健康越来越呈现出强大的影响力和生命力,对推进深化医药卫生体制改革、加快“健康中…...

    2024/4/25 3:28:28
  15. 不会吧!做了这么久开发还有不会NIO的,看看BAT大佬是怎么用的吧

    前言在将NIO之前,我们必须要了解一下Java的IO部分知识。 BIO(Blocking IO) 阻塞IO,在Java中主要就是通过ServerSocket.accept()实现的。 NIO(Non-Blocking IO) 非阻塞IO,在Java主要是通过NIOSocketChannel + Seletor实现的。 AIO(Asyc IO) 异步IO,目前不做学习。BIO …...

    2024/4/17 22:52:55
  16. 2020年 第11届 蓝桥杯 C/C++ B组 省赛真题详解及小结【第1场省赛2020.7.5】

    蓝桥杯 Java B组 省赛真题详解及小结汇总【2013年(第4届)~2020年(第11届)】2013年 第04届 蓝桥杯 Java B组 省赛真题详解及小结2014年 第05届 蓝桥杯 Java B组 省赛真题详解及小结2015年 第06届 蓝桥杯 Java B组 省赛真题详解及小结2016年 第07届 蓝桥杯 Java B组 省赛真题详解…...

    2024/5/8 19:35:01
  17. 如何找到最适合您的开源项目

    如何找到最适合您的开源项目?BY 若欲莹,巴蒂尔王 ON 2019年9月17日边缘计算当前是计算行业中最普遍的主题之一。它是一项广泛的技术,几乎可以使每个行业都受益,这就是为什么出现了如此多的用例和项目的原因。本文介绍了边缘分类,描述了边缘用例的特征,概述了市场上可用的…...

    2024/4/27 18:22:41
  18. 高性能开发

    高性能开发最简单的网络通信模型:正常网络通信数据拷贝零拷贝技术I/O优化:多路复用技术线程池技术无锁编程技术wait-freelock-freeobstruction-freeLock-free CASCAS的缺点:ABA问题解决Wait-free进程间通信技术RPC && 序列化技术RPC序列化技术ProtoBufThriftAvro数据…...

    2024/5/8 17:57:25
  19. Pycharm 常用快捷键

    常用快捷键快捷键功能Ctrl + Q 快速查看文档Ctrl + F1 显示错误描述或警告信息Ctrl + / 行注释(可选中多行)Ctrl + Alt + L 代码格式化Ctrl + Alt + O 自动导入Ctrl + Alt + I 自动缩进Tab / Shift + Tab 缩进、不缩进当前行(可选中多行)Ctrl+C/Ctrl+Insert 复制当前行或选…...

    2024/4/15 5:30:08
  20. Django基础4--Shell及管理页面

    1.Django Shell打开Django的命令交互模式(django) ➜ AutoPlatform python manage.py shell Python 3.7.5 (default, Nov 29 2019, 14:32:46) [Clang 9.0.0 (clang-900.0.39.2)] on darwin Type "help", "copyright", "credits" or "lice…...

    2024/4/11 21:39:19

最新文章

  1. 保护公司机密:避免员工带着数据说拜拜

    公司的核心资产之一就是数据。无论是客户信息、研发代码、内部决议、财务报告、商业合同、设计图纸等都是公司的重要资产。如果这些数据在员工离职时被带走&#xff0c;或在员工在职期间不当行为导致数据泄露&#xff0c;将给公司带来重大损失。 然而&#xff0c;保护这些数据…...

    2024/5/9 3:19:06
  2. 梯度消失和梯度爆炸的一些处理方法

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

    2024/5/7 10:36:02
  3. 第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组 题解

    VP比赛链接 : 数据加载中... - 蓝桥云课 1 . 九进制 转 十进制 直接模拟就好了 #include <iostream> using namespace std; int main() {// 请在此输入您的代码int x 22*92*81*9;cout << x << endl ;return 0; } 2 . 顺子日期 枚举出每个情况即可 : …...

    2024/5/6 13:50:47
  4. Claude-3全解析:图片问答,专业写作能力显著领先GPT-4

    人工智能技术的飞速发展正在深刻改变着我们的工作和生活方式。作为一名资深的技术爱好者&#xff0c;我最近有幸体验了备受瞩目的AI助手Claude-3。这款由Anthropic公司推出的新一代智能工具展现出了非凡的实力&#xff0c;尤其在图像识别和专业写作领域的表现更是让人眼前一亮&…...

    2024/5/6 11:14:45
  5. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/5/8 19:32:33
  6. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/5/7 22:31:36
  7. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/5/9 2:44:26
  8. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/5/8 20:33:13
  9. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/5/9 3:15:57
  10. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/5/7 16:57:02
  11. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/5/7 14:58:59
  12. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/5/8 20:58:56
  13. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/5/9 1:35:21
  14. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/5/8 1:37:35
  15. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/5/7 16:05:05
  16. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/5/8 18:06:50
  17. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/5/8 1:37:32
  18. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/5/9 1:42:21
  19. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/5/8 1:37:31
  20. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/5/8 1:37:31
  21. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/5/8 12:44:41
  22. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/5/8 9:51:44
  23. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/5/8 1:37:29
  24. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/5/7 17:09:45
  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