面试(05)————Redis篇

目录

一、项目中哪些地方使用了redis

 问题一:发生了缓存穿透该怎么解决?

方案一:缓存空数据

方案二:布隆过滤器

模拟面试

问题二: 发生了缓存击穿该怎么解决?

 方案一:互斥锁

 方案二:逻辑过期 

 模拟面试

问题三: 发生了缓存雪崩该怎么解决?

问题四: redis作为缓存,mysql的数据如何redis进行同步?(双写一致性)

 这个时候我们就要考虑是先删除缓存,还是先修改数据库?

情况一:先删除缓存,再操作数据库

情况二:先操作数据库,再删除缓存

那么为什么要删除两次缓存? 

为什么要延时删除?

业务场景一:那怎么保证双写一致呐?(一致性要求高的业务需求)

 业务场景二:延迟一致怎么做?(允许短暂的不一致,实际开发中最为主流的)

方案一:基于MQ的异步通知

方案二:基于Canal的异步通知

 模拟面试

 问题五:redis作为缓存,数据的持久化是怎么做的?

 RDB

AOF

RDB与AOD对比 

模拟面试

​编辑 问题六:假设redis的key过期之后,会立即删除吗?(数据过期策略)

惰性删除 

定期删除 

模拟面试 

问题七: 假如缓存过多,内存是有限的,内存被占满了怎么办?(数据淘汰策略)

关于数据淘汰策略其他的面试问题?

1、数据库有1000万数据,Redis只能缓存20w数据,如何保证Redis中的数据都是热点数据?

2、Redis的内存用完了会发生什么?

模拟面试

问题八:redis分布式锁,是如何实现的?

情景模拟———抢券执行

redis分布式锁

Redis实现分布式锁如何合理的控制锁的有效时长?

redisson实现的分布式锁——执行流程

redisoon实现的分布式锁,是否可以重入呐?

redisson实现的分布式锁——主从一致性

模拟面试

问题九:redis集群有哪些方案?

 主从复制

主从全量同步

主从增量同步 (slave重启或后期数据变化)

模拟面试

 哨兵的作用

结构

作用

服务状态监控

Redis集群(哨兵模式)脑裂

模拟面试

分片集群结构

数据读写 

模拟面试

 总结

 问题十:Redis是单线程的,但是为什么还那么快?

能解释一下I/O多路复用 模型?

 用户空间和内核空间

阻塞IO

非阻塞IO

IO多路复用 

 Redis网络模型

模拟面试


以下问题包括知识点和面试题,看的时候直接看《模拟面试即可》,后续持续更新中。。。 

一、项目中哪些地方使用了redis

面试官:我看你做的项目中,都用到了redis,你在最近的项目中哪些场景使用了redis?

 一般这个问题要结合自己的实际项目经历回答,面试想这样问:一方面验证你的项目场景的真实性,二是为了作为深入发问的切入点

比如你回答了使用了:(可能会被问道的相关问题或知识点)

缓存:缓存三兄弟(穿透、击穿、雪崩)、双写一致、持久化、数据过期策略、数据淘汰策略
 

分布式锁:setnx、redisson
 

消息队列、延迟队列:何种数据类型

 问题一:发生了缓存穿透该怎么解决?

以下是正常使用缓存的流程:

那么什么是缓存穿透呐?

查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都去查询数据库

 那为什么会出现这种情况呐?

通常呐,就是有人恶意攻击你的系统,有人知道你的请求路径,知道你的请求参数跟在请求路径后面的,就会制造一些假的id发起请求等等,就会冲击你的数据库,你的数据库的并发是不高的,请求到了一定的量就会击垮数据库。

 解决方案:

方案一:缓存空数据

解决方案一:缓存空数据,查询返回的数据为空,仍把这个空数据进行缓存

优点:操作简单

缺点:消耗内存,可能会发生不一致的问题

方案二:布隆过滤器

 解决方案二:布隆过滤器

优点:内存占用较少,没有多余key

缺点:实现复杂,存在误判

布隆过滤器:


bitmap(位图):相当于一个以(bit)位为单位的数组,数组中每个单元只能存储二进制数0或1

布隆过滤器作用:布隆过滤器可以用于检索一个元素是否再一个集合中。

可能产生误判:

误判率:数组越小误判率就越大,数组越大误判率就越小,但是同时带来了更多的内存消耗

模拟面试

问题二: 发生了缓存击穿该怎么解决?

什么是缓存击穿?

给某一个key设置了过期时间,当key过期的时候,恰好这时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把数据库压垮

 解决方案:

 方案一:互斥锁

特点:强一致,性能差

 方案二:逻辑过期 

特点:高可用、性能优、不能保证数据的绝对一致

 模拟面试

问题三: 发生了缓存雪崩该怎么解决?

什么是缓存雪崩?

在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力

解决方案:

  • 给不同的key的TTL添加随机值
  • 利用Redis集群提高服务的可用性
  • 给缓存业务添加降级限流策略  (降级可作为系统的保底策略,适用于穿透、击穿、雪崩)
  • 给业务添加多级缓存

 模拟面试:

问题四: redis作为缓存,mysql的数据如何redis进行同步?(双写一致性)

一定要设置前提,,,结合自己的项目业务背景去讲!!!!

看看到底属于哪一种:是一致性要求高的业务需求,还是说是允许延迟一致?

双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致

读操作:缓存命中,直接返回;缓存未命中查询数据库,写入缓存,设定超时时间

写操作:延迟双删 

 这个时候我们就要考虑是先删除缓存,还是先修改数据库?

情况一:先删除缓存,再操作数据库

正常情况:

不正常情况:因为线程是交替执行的,这种方式可能会出现脏数据的现象

情况二:先操作数据库,再删除缓存

正常情况:

不正常情况:这种方式可能会出现脏数据的现象

那么为什么要删除两次缓存? 

降低脏数据的出现

为什么要延时删除?

业务场景一:那怎么保证双写一致呐?(一致性要求高的业务需求)

但是这样的话,性能就有点差了

当然我们都是知道的,放入redis的数据一般都是读多写少

所以使用读写锁就可以了

特点:强一致,性能差(强一致性情况下才会使用)

共享锁:读锁readLock,加锁之后,其他线程可以共享读操作

排他锁:独占锁writeLock,加锁之后,阻塞其他线程读写操作

 业务场景二:延迟一致怎么做?(允许短暂的不一致,实际开发中最为主流的)

方案一:基于MQ的异步通知

方案二:基于Canal的异步通知

 模拟面试

强一致性回答:

最终一致性回答:

 问题五:redis作为缓存,数据的持久化是怎么做的?

 RDB

什么是RDB呐?

RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中所有数据记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,回复数据

人工主动备份:

Redis自动备份:

Redis内部有触发RDB的机制,可以再redis.conf文件中找到,格式如下:

 RDB的执行原理:

bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入RDB文件。

fork采用的是copy-write技术:

  • 当主进程执行读操作时,访问共享内存;
  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作。

优点 :

1. 整个Redis数据库将只包含⼀个⽂件 dump.rdb,⽅便持久化。
2. 容灾性好,⽅便备份。
3. 性能最⼤化,fork ⼦进程来完成写操作,让主进程继续处理命令,所以是 IO 最⼤化。使⽤单独⼦
进程来进⾏持久化,主进程不会进⾏任何 IO 操作,保证了 redis 的⾼性能
4. 相对于数据集⼤时,⽐ AOF 的启动效率更⾼。
 
缺点:
1. 数据安全性低。RDB 是间隔⼀段时间进⾏持久化,如果持久化之间 redis 发⽣故障,会发⽣数据丢
失。所以这种⽅式更适合数据要求不严谨的时候)
2. 由于RDB是通过fork⼦进程来协助完成数据持久化⼯作的,因此,如果当数据集较⼤时,可能会导
致整个服务器停⽌服务⼏百毫秒,甚⾄是1秒钟

AOF

什么是AOF呐?

AOF全称Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看作是命令日志文件。


优点:

1. 数据安全,Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也
是异步完成的,其效率也是⾮常⾼的,所差的是⼀旦系统出现宕机现象,那么这⼀秒钟之内修改的
数据将会丢失。⽽每修改同步,我们可以将其视为同步持久化,即每次发⽣的数据变化都会被⽴即
记录到磁盘中。。
2. 通过 append 模式写⽂件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过 redis
check-aof ⼯具解决数据⼀致性问题。
3. AOF 机制的 rewrite 模式。定期对AOF⽂件进⾏重写,以达到压缩的⽬的

缺点:

1、 因为是记录命令,AOF文件会比RDB文件大得多。而且AOF会记录对同一个key的多次写操作,单只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同的效果。

2、 数据集⼤的时候,⽐ rdb 启动效率低。
3、运⾏效率没有RDB⾼

 Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:

RDB与AOD对比 

模拟面试

 问题六:假设redis的key过期之后,会立即删除吗?(数据过期策略)

什么是数据过期策略呐?

Redis对数据设置数据的有效时间,数据过期以后,就需要将数据从内存中删除掉。可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略)

惰性删除 

惰性删除:设置该key过期时间后,我们不去管它,当需要该key时,我们再检查其是否过期,如果过期,我们就删掉它,反之返回该key

 优点:对CPU友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查

缺点:堆内存不好,如果一个key已经过期,但是一直没有使用,那么该key就会一直存在内存中,内存永远不会释放

定期删除 

什么是定期删除呐?

每隔一段时间,我们就对一些key进行检查,删除里面过期的key(从一定数量的数据库中取出一定数量的随机key进行检查,并删除其中的过期key)。

定期清理的两种模式

  • SLOW模式 是定时任务,执行频率默认为10hz,每次不超过25ms,以通过修改配置文件redis.conf的hz选项来调整这个次数
  • FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms

优点: 可以通过限制删除操作执行的时长和频率来减少删除操作对CPU的影响。另外定期删除,也能有效释放过期键占用的内存。


缺点:难以确定删除操作执行的时长和频率。

 Redis的过期删除策略:惰性删除 + 定期删除两种策略进行配合使用

模拟面试 

问题七: 假如缓存过多,内存是有限的,内存被占满了怎么办?(数据淘汰策略)

什么是数据淘汰策略?

当Redis中的内存不够用时,此时再向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。

 LRU例子:key1是在3s之前访问的,key2是在9s之前访问的,删除的就是key2

LFU例子:key1最近5s访问了4次,key2最近5s访问了9次,删除的就是key1

 

关于数据淘汰策略其他的面试问题?

1、数据库有1000万数据,Redis只能缓存20w数据,如何保证Redis中的数据都是热点数据?

2、Redis的内存用完了会发生什么?

模拟面试

以上问题都是基于你的项目:redis使用的场景是缓存这部分;下面则是基于你的项目redis使用场景是分布式锁

问题八:redis分布式锁,是如何实现的?

情景模拟———抢券执行

正常情况:

异常情况:

当线程1执行完,此时的库存是0,当线程2执行完之后,库存再减一,就变成-1了,就会出现超卖的情况

加锁操作:

适用于单体项目,服务只部署在一台服务器上的,这个方法是没问题的,但是往往我们的服务都是集群的

分布式锁解决这个问题:

redis分布式锁

Redis实现分布式锁主要利用Redis的setnx命令。setnx是SET if not exists(如果不存在,则SET)的缩写。



 

1. ⾸先利⽤setnx来保证:如果key不存在才能获取到锁,如果key存在,则获取不到锁
2. 然后还要利⽤lua脚本来保证多个redis操作的原⼦性
3. 同时还要考虑到锁过期,所以需要额外的⼀个看⻔狗定时任务来监听锁是否需要续约
4. 同时还要考虑到redis节点挂掉后的情况,所以需要采⽤红锁的⽅式来同时向N/2+1个节点申请锁,
都申请到了才证明获取锁成功,这样就算其中某个redis节点挂掉了,锁也不能被其他客户端获取到

Redis实现分布式锁如何合理的控制锁的有效时长?

根据业务执行时间预估
 

给锁续期

redisson实现的分布式锁——执行流程

实例代码:

redisoon实现的分布式锁,是否可以重入呐?

可重入,利用hash结构记录线程id和重入次数

redisson实现的分布式锁——主从一致性

RedLock(红锁):不能只在一个redis实例上创建锁,应该是在多个redis实例上创建锁(n/2+1),避免在一个redis实例上加锁。

模拟面试

下面则是redis其他的问题

问题九:redis集群有哪些方案?

主从复制

哨兵模式

分片集群

 主从复制

 单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。


 

通过执⾏slaveof命令或设置slaveof选项,让⼀个服务器去复制另⼀个服务器的数据。主数据库可以进 ⾏读写操作,当写操作导致数据变化时会⾃动将数据同步给从数据库。⽽从数据库⼀般是只读的,并接 受主数据库同步过来的数据。⼀个主数据库可以拥有多个从数据库,⽽⼀个从数据库只能拥有⼀个主数据库。

主从全量同步

1. 主节点通过bgsave命令fork⼦进程进⾏RDB持久化,该过程是⾮常消耗CPU、内存(⻚表复制)、硬
盘IO的
2. 主节点通过⽹络将RDB⽂件发送给从节点,对主从节点的带宽都会带来很⼤的消耗
3. 从节点清空⽼数据、载⼊新RDB⽂件的过程是阻塞的,⽆法响应客户端的命令;如果从节点执⾏
bgrewriteaof,也会带来额外的消耗

主从增量同步 (slave重启或后期数据变化)

1. 复制偏移量:执⾏复制的双⽅,主从节点,分别会维护⼀个复制偏移量offset
2. 复制积压缓冲区:主节点内部维护了⼀个固定⻓度的、先进先出(FIFO)队列 作为复制积压缓冲区,
当主从节点offset的差距过⼤超过缓冲区⻓度时,将⽆法执⾏部分复制,只能执⾏全量复制。
3. 服务器运⾏ID(runid):每个Redis节点,都有其运⾏ID,运⾏ID由节点在启动时⾃动⽣成,主节点会
将⾃⼰的运⾏ID发送给从节点,从节点会将主节点的运⾏ID存起来。 从节点Redis断开重连的时
候,就是根据运⾏ID来判断同步的进度:
如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会继续
尝试使⽤部分复制(到底能不能部分复制还要看offset和复制积压缓冲区的情况);
如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的Redis节点并不
是当前的主节点,只能进⾏全量复制。

模拟面试

 哨兵的作用

Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复

结构

作用

服务状态监控

Redis集群(哨兵模式)脑裂

模拟面试

分片集群结构

 

数据读写 

Redis分片集群引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽

模拟面试

 总结

Redis提供了三种集群策略:
1. 主从模式:这种模式⽐较简单,主库可以读写,并且会和从库进⾏数据同步,这种模式下,客户端 直接连主库或某个从库,但是但主库或从库宕机后,客户端需要⼿动修改IP,另外,这种模式也⽐ 较难进⾏扩容,整个集群所能存储的数据受到某台机器的内存容量,所以不可能⽀持特⼤数据量
2. 哨兵模式:这种模式在主从的基础上新增了哨兵节点,但主库节点宕机后,哨兵会发现主库节点宕 机,然后在从库中选择⼀个库作为进的主库,另外哨兵也可以做集群,从⽽可以保证但某⼀个哨兵 节点宕机后,还有其他哨兵节点可以继续⼯作,这种模式可以⽐较好的保证Redis集群的⾼可⽤,但 是仍然不能很好的解决Redis的容量上限问题。
3. Cluster模式:Cluster模式是⽤得⽐较多的模式,它⽀持多主多从,这种模式会按照key进⾏槽位的 分配,可以使得不同的key分散到不同的主节点上,利⽤这种模式可以使得整个集群⽀持更⼤的数据容量,同时每个主节点可以拥有⾃⼰的多个从节点,如果该主节点宕机,会从它的从节点中选举⼀ 个新的主节点。
对于这三种模式,如果Redis要存的数据量不⼤,可以选择哨兵模式,如果Redis要存的数据量⼤,并且 需要持续的扩容,那么选择Cluster模式。

 问题十:Redis是单线程的,但是为什么还那么快?

能解释一下I/O多路复用 模型?

 用户空间和内核空间

阻塞IO

非阻塞IO

IO多路复用 

IO多路复用:是利用单个线程来同时监听多个Socket,并在某个Socket可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。不过监听Scoket的方式、通知的方式又有多种实现,常见的有:

select

poll

epoll

 Redis网络模型

Redis通过IO多路复用来提高网络性能,并支持各种不同的多路复用实现,并且将这些实现进行封装,提供了统一的高性能事件库

模拟面试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/1187.shtml

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

相关文章

Python数据可视化:频率统计条形图countplot()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 Python数据可视化: 频率统计条形图 countplot() [太阳]选择题 请问关于以下代码表述正确的选项是? import seaborn as sns import matplotlib.pyplot as plt data { …

断言(Assertion)在IT技术中的确切含义— 基于四类典型场景的分析

当“断言”(Assertion)一词成为IT术语时,语义的混沌性和二义性也随之而生。那么,何为断言?断言何为?实际上,只需分析四种典型场景,确切答案和准确描述就将自然显现。 在SAML&#xf…

Scikit-Learn

机器学习中的重要角色 Scikit-Leran(官网:https://scikit-learn.org/stable/),它是一个基于 Python 语言的机器学习算法库。Scikit-Learn 主要用 Python 语言开发,建立在 NumPy、Scipy 与 Matplotlib 之上,…

【python】使用python和selenium实现某平台自动化上传作品的全步骤

第一,我们需要下载python并安装 下载地址:https://www.python.org/downloads/release/python-3123/ 3.x版本的python自带pip工具,因此不需要额外下载。 ModuleNotFoundError: No module named seleniumpip用于下载python适用的各类模块&…

Proxy 代理

意图 为其它对象提供一种代理以控制这个对象的访问。 结构 Proxy保存一个引用使得代理可以访问实体;提供一个与Subject的接口相同的接口,使代理可以用来替代实体;控制实体的存取,并可能负责创建和删除它;其他功能依赖…

用户体验至上:独立站脱颖而出的关键要素解析

在数字化时代,独立站成为了许多品牌和企业展示自身形象、推广产品、建立客户联系的重要平台。然而,要想在众多的独立站中脱颖而出,吸引并留住用户,良好的用户体验至关重要。本文Nox聚星将和大家探讨如何做好独立站的用户体验&…

【Linux深造日志】运维工程师必会Linux常见命令以及周边知识!

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《linux深造日志》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引入 哈喽各位宝子们好啊!我是博主鸽芷咕。日志这个东西我相信大家都不陌生,在 linxu/Windows 系统…

【自定义类型详解】完结篇——联合体(共用体)与枚举详解

先赞后看已成习惯!!! 联合体 1. 联合体的定义 联合体又叫共用体,它是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。给联合体其中⼀个成员赋值,其他成员的值也会跟着变化。 联合体的结…

kaggle 房价预测 得分0.53492

流程 导入需要的包引入文件,查看内容数据处理调用模型准备训练输出结果 导入需要的包 import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.model_selection import train_test_split from sklearn.linear_model i…

适合各大资源网投稿html源码

源码介绍 适合各大资源网投稿html源码,源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果,也可以上传到服务器里面,重定向这个界面 效果预览 源码下载 适合各大资源…

数据分析(1)

数据分析基础(1) 为了让刚开始学习的朋友对数据分析有一个清晰的整体认识,因此笔者在此对数分进行一个较为详细的介绍有助于大家更好的在宏观层面进行理解,避免在后续学习中产生迷茫。 数据分析的概念 定义:数据分析…

Oracle体系结构初探:聊聊REDO

上一篇文章写了undo(文章链接:聊聊UNDO),这篇和大家一起聊聊redo。redo如果按照我的傻瓜翻译,意为再次去做、重新去做。Oracle官方对于redo的描述是:记录对数据所做的所有更改,包括未提交和已提…

Vue3——组件基础

组件基础 1. 组件定义与使用 1.1 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>组件基础&l…

Docker - 镜像、容器、仓库

原文地址&#xff0c;使用效果更佳&#xff01; Docker - 镜像、容器、仓库 | CoderMast编程桅杆Docker - 镜像、容器、仓库 提示 这个章节涉及到 Docker 最核心的知识&#xff0c;也是在使用过程中最常使用到的&#xff0c;需要重点学习。 什么是Docker镜像、容器、仓库&…

leetcode:438. 找到字符串中所有字母异位词

给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括相同的字符串&#xff09;。 示例 1: 输入: s "cbaebabacd", p "…

前端工程化01-复习jQuery当中的AJAX

4.1、基础概念 什么是服务器 一台存储网站内容、网站文件的电脑 什么是资源 网站中使用的文件&#xff08;html、css、图片、…&#xff09;这些东西就叫做资源数据也是服务器上的资源&#xff0c;而且是一个网站的灵魂 客户端 客户端应该指上网的设备但是在前端开发中&a…

Web后端-请求响应

黑马程序员JavaWeb开发教程 文章目录 一、请求1、简单参数2、实体参数3、数组集合参数&#xff08;1&#xff09;数组参数&#xff08;2&#xff09;集合参数 4、日期参数5、json参数&#xff08;1&#xff09;在Postman中怎么发起请求来传递JSON格式的请求参数&#xff08;2&a…

精通MongoDB聚合操作API:深入探索高级技巧与实践

MongoDB 聚合操作API提供了强大的数据处理能力&#xff0c;能够对数据进行筛选、变换、分组、统计等复杂操作。本文介绍了MongoDB的基本用法和高级用法&#xff0c;高级用法涵盖了setWindowFields、merge、facet、expr、accumulator窗口函数、结果合并、多面聚合、查询表达式在…

卷王问卷考试系统/SurveyKing调查系统源码

SurveyKing是一个功能强大的开源调查问卷和考试系统&#xff0c;它能够快速部署并适用于各个行业。 这个系统提供了在线表单设计、数据收集、统计和分析等功能&#xff0c;支持20多种题型&#xff0c;提供多种创建问卷的方式和设置。 项 目 地 址 &#xff1a; runruncode.c…

C++相关概念和易错语法(7)(初始化列表、隐式类型转换、友元)

1.初始化列表 初始化列表是集成在构造函数里面的&#xff0c;对象在创建的时候一定会调用构造函数&#xff08;就算不显式定义&#xff0c;也会自动生成并调用&#xff09;。初始化列表就是这些对象的成员变量在创建的时候初始化的地方。 下面是使用的例子&#xff0c;可以先…