大家好,我是阿Q。
今天带大家看一位同学在美团面试过程中遇到的问题,用他的原话说就是“体验感极佳,效果极差”。面试过程中,和面试官交流的情况还是可以的,奈何自己多少差点意思,后边儿还是挂了。。。
我也看了下这些问题,算基础但是也不算简单,中间有的问题问得还是挺深的,大家可以借鉴,也许有收获呢?
主页还有其它公司的面经,大家感兴趣可点进去关注,多看看呢。
下面是今天的原文:
1、UDP、TCP区别?
连接性: TCP:TCP是一种面向连接的协议。这意味着在数据传输之前,必须建立一个连接。连接在通信结束后会被明确地关闭。TCP确保了可靠的数据传输,因为它使用确认机制来确保数据的完整性和顺序性。 UDP:UDP是一种面向无连接的协议。它不需要在通信开始之前建立连接,也不需要在通信结束后关闭连接。UDP不提供可靠性,因此无法保证数据的完整性和顺序性。 数据传输方式: TCP:TCP提供流式传输,数据被分割成小的数据块(通常称为数据段),然后按照顺序发送和接收。TCP确保了数据的有序性,如果数据包丢失或损坏,它会重新发送。 UDP:UDP以数据报的形式传输数据,每个数据包都是独立的,不与其他数据包相关。这意味着UDP不会维护数据包的顺序,也不会重新发送丢失的数据包。 可靠性: TCP:TCP提供可靠性的通信,它使用确认机制来确保数据的完整性和顺序性。如果数据包丢失或损坏,TCP会重新发送它们,直到对方确认接收为止。 UDP:UDP不提供可靠性,它不使用确认机制,也不会重新发送丢失的数据包。这使得UDP更适合那些对实时性要求高,但可以容忍一些数据丢失的应用,如视频流或音频通话。 拥塞控制: TCP:TCP具有拥塞控制机制,它可以调整数据传输速率,以适应网络拥塞情况,从而避免网络过载和数据丢失。 UDP:UDP不具备拥塞控制机制,因此在网络拥塞时可能导致数据丢失或丢失的数据包增加。 适用场景: TCP:TCP适用于需要可靠传输的应用,如网页浏览、电子邮件、文件传输等,其中数据的完整性和顺序性至关重要。 UDP:UDP适用于那些对实时性要求高,可以容忍一些数据丢失的应用,如实时视频流、音频通话、在线游戏等。
半开连接:在正常情况下,服务器会发送一个ACK(确认)数据包作为对客户端的第三次握手的响应。这个ACK告诉客户端,服务器已经准备好接受数据,并且连接已经建立。如果第三次握手丢失,客户端将不会收到这个确认,从而导致客户端认为连接未建立,而服务器却认为连接已建立。 资源浪费:服务器会分配一些资源来处理建立的TCP连接,如内存、CPU时间等。如果第三次握手丢失,服务器可能会一直等待客户端的确认,而这个连接不会被完全建立。这将导致服务器浪费资源,因为它无法回收已分配的资源。 连接保持:在某些情况下,如果第三次握手丢失,服务器可能会保持连接状态一段时间,直到超时或其他机制触发。这会导致服务器上的连接资源被占用,可能会影响其他客户端的连接请求。 客户端重试:由于客户端没有收到服务器的确认,它可能会认为连接建立失败,并尝试重新建立连接。这可能会导致客户端发起多次连接尝试,增加网络负载和服务器资源消耗。
使用流式传输和分块处理:对于大文件,不要尝试一次性将整个文件加载到内存中,而是使用流式传输(streaming)和分块处理(chunking)的方式。将大文件分成较小的块,逐块传输和处理,以减少内存占用和提高效率。 调整TCP缓冲区大小:要处理大流量,可能需要调整TCP缓冲区的大小,以确保能够容纳足够的数据。较大的缓冲区可以帮助提高吞吐量和性能。但是要注意不要设置过大的缓冲区,以避免浪费内存和引发拥塞控制问题。 使用多线程或多进程:对于大文件和大流量,可以考虑使用多线程或多进程来并行处理数据。这可以提高处理速度,充分利用多核处理器。 实现流控制:使用TCP窗口大小来实现流控制,以确保发送方和接收方之间的数据传输速度匹配。这可以帮助防止拥塞并提高性能。 数据压缩:如果适用,可以在传输大文件之前对数据进行压缩,以减少传输的数据量。这可以降低网络带宽的要求,并提高传输速度。 优化文件传输协议:考虑使用专门设计用于大文件传输的协议或工具,如FTP(文件传输协议)或HTTP的分块传输功能。这些协议通常针对大文件传输进行了优化。 错误处理和恢复:在处理大文件和大流量时,要考虑到网络中可能发生的错误,如丢包或连接中断。实现适当的错误处理和恢复机制,以确保数据的可靠性和完整性。 负载均衡:如果有大量客户端连接到服务器并请求大文件,考虑使用负载均衡技术,将流量分散到多个服务器实例上,以分担服务器负载。 监控和调优:实时监控系统性能,以及时发现问题并进行调优。使用性能分析工具来识别性能瓶颈并采取适当的措施来提高性能。
IP到MAC地址映射:ARP的主要功能是将IP地址映射到对应的MAC地址。在一个局域网中,通信设备使用MAC地址来唯一标识自己,但在网络层(例如,使用IPv4)中,设备使用IP地址来标识。当一台设备需要向另一台设备发送数据包时,它需要知道目标设备的MAC地址才能正确地将数据包交付给目标。 ARP请求和响应:ARP工作通过ARP请求和ARP响应两个步骤来完成。当一个设备需要解析一个IP地址时,它会广播一个ARP请求到网络上的所有设备,请求包含了目标IP地址。接收到这个ARP请求的设备会检查请求中的IP地址是否与自己的IP地址匹配。如果匹配,设备将发送一个ARP响应,包含自己的MAC地址。ARP响应会返回给ARP请求的发起者,从而该发起者获得了目标设备的MAC地址。 ARP缓存:设备在解析IP地址时会维护一个ARP缓存表,用于存储最近解析过的IP地址和对应的MAC地址。这可以减少ARP请求的频率,提高网络性能。ARP缓存表中的记录通常有一个生存时间,一段时间后会被删除,以便及时更新。 ARP欺骗检测:ARP协议中存在一种安全风险,称为ARP欺骗(ARP spoofing)或ARP缓存投毒攻击。为了应对这种攻击,一些网络设备和协议实现支持ARP欺骗检测,可以识别并阻止恶意ARP响应,以确保正确的IP到MAC地址映射。 IPv6中的NDP替代:在IPv6网络中,使用NDP(Neighbor Discovery Protocol)来实现类似ARP的功能,但它同时处理了更多的网络配置和路由信息。
当一台设备需要将数据包发送给另一台设备时,它首先会检查本地的ARP缓存表,查找目标IP地址是否已经在表中有对应的MAC地址。 如果目标IP地址在ARP缓存表中找到了对应的MAC地址,设备可以直接使用这个MAC地址来构建数据包,并将数据包发送到目标。 如果ARP缓存表中没有目标IP地址的条目,设备将需要执行ARP解析,即向局域网上的所有设备发送一个ARP请求。 ARP请求包含了需要解析的目标IP地址,以及发送设备的自身IP和MAC地址。 所有接收到这个ARP请求的设备都会检查请求中的IP地址是否与自己的IP地址匹配。如果匹配,设备将发送一个ARP响应,包含自己的MAC地址。 发起ARP请求的设备将收到的ARP响应中的MAC地址存储在本地ARP缓存表中,并将数据包发送给目标设备的MAC地址。 同时,其他设备也会将发起ARP请求的设备的IP和MAC地址存储在本地ARP缓存表中,以便将来的通信。
数据传输方式: GET:使用URL来传输数据。GET请求将数据附加在URL的末尾,以查询字符串(query string)的形式发送到服务器。例如, http://example.com/page?name=John&age=30
。POST:使用HTTP消息主体来传输数据。POST请求将数据放在HTTP请求的主体部分,而不是在URL中,因此对于传输敏感数据更安全。 数据大小限制: GET:由于数据附加在URL中,受到URL长度的限制,不适合传输大量数据。各浏览器和服务器可能对URL长度有不同的限制。 POST:没有固定的数据大小限制,可以传输大量数据,通常用于上传文件或提交表单等需要传输大块数据的场景。 安全性: GET:因为数据在URL中可见,所以不适合传输敏感信息,如密码。GET请求的数据可以被浏览器缓存、代理服务器记录、以及保存在浏览器的历史记录和书签中,因此不太安全。 POST:由于数据在HTTP主体中,更适合传输敏感信息,如登录凭证。POST请求的数据不会被浏览器缓存,也不会出现在URL中,因此相对较安全。 缓存: GET:默认情况下,GET请求可以被浏览器缓存,以提高性能。如果同一个GET请求被多次发送,浏览器可能会直接从缓存中获取响应,而不重新请求服务器。 POST:默认情况下,POST请求不会被浏览器缓存,因为它通常用于对服务器执行某种操作,而不是只获取数据。 书签和历史记录: GET:由于GET请求的数据可以出现在URL中,所以它们适合用于创建书签和保存在浏览器的历史记录中。这使得用户可以轻松地保存和分享链接。 POST:POST请求的数据不会出现在URL中,因此不适合创建书签或保存在浏览器的历史记录中。 幂等性: GET:GET请求是幂等的,多次请求相同的URL会产生相同的结果,不会对服务器产生影响。因此,GET请求通常用于获取资源。 POST:POST请求通常不是幂等的,多次请求相同的URL可能会产生不同的结果,可能会对服务器产生影响,如创建新资源或修改数据。
ls:列出目录中的文件和子目录。cd:更改当前工作目录。pwd:显示当前工作目录的路径。mkdir:创建新目录。rmdir:删除空目录。touch:创建新文件或更新文件的时间戳。cp:复制文件或目录。mv:移动或重命名文件或目录。rm:删除文件或目录。cat:连接和显示文件的内容。more less:逐页显示文件内容。head tail:显示文件的开头或结尾部分。grep:在文件中搜索文本,支持正则表达式。ps:显示当前运行的进程。top:动态显示系统进程信息。kill:终止进程。chmod:修改文件或目录的权限。chown:更改文件或目录的所有者。df:显示磁盘使用情况。du:显示目录和文件的磁盘使用情况。find:在文件系统中查找文件或目录。tar:创建或解压归档文件。wget:从网络下载文件。curl:用于与网络资源进行数据交互。ssh:通过安全的Shell连接远程服务器。scp:在本地和远程系统之间安全地复制文件。rsync:用于本地和远程文件同步。ping:测试与远程主机的网络连接。ifconfig ip:显示和配置网络接口信息。lsof:列出打开的文件和网络连接。sed:流文本编辑器,用于文本处理和替换。awk:用于处理文本数据,支持自定义操作。crontab:用于设置定时任务。sudo:以超级用户权限执行命令。nc (netcat):用于网络工具,可以用于端口扫描、端口监听、数据传输等。nmap:用于网络探测和安全性扫描。traceroute:跟踪数据包在网络上的路径。htop:交互式进程查看器,显示系统资源使用情况。diff:比较文件和目录之间的差异。zip unzip:创建和解压ZIP归档。history:显示已执行的命令历史记录。shutdown:关闭或重启系统。reboot:重新启动系统。
互斥条件(Mutual Exclusion):这意味着某些资源只能被一个进程或线程占用,其他进程或线程不能同时访问。如果一个进程已经获得了某个资源,其他进程就必须等待该资源被释放。 占有且等待条件(Hold and Wait):进程至少持有一个资源,并且正在等待获取其他进程占有的资源。换句话说,即使进程没有获取所有需要的资源,它也可以继续执行,并在等待其他资源时保持已经获取的资源。 非抢占条件(No Preemption):资源不能被强制性地从一个进程中抢占并分配给另一个进程。只能在持有资源的进程主动释放资源后,其他进程才能获取。 循环等待条件(Circular Wait):存在一个资源等待链,其中每个进程都在等待下一个进程所持有的资源,最终形成一个循环。例如,进程A等待进程B的资源,进程B等待进程C的资源,进程C等待进程A的资源。
破坏请求和保持条件
破坏“请求”条件(预先静态分配法)
资源利用率很低:有些资源可能在最后才会用到,它却一直占用了很久。 进程可能出现饥饿现象:可能由于个别资源被其他进程占用而导致某进程迟迟不能开始。 破坏“保持”条件
破坏非抢占条件
走不通就放弃自己的已有资源造福别人
走不通先去抢别人的(前提是别人也走不通),抢不到就放弃自己的
有的资源是不可抢占资源,比如打印机,被抢占后可能导致前一阶段的工作失效。 延长了周转时间,降低了系统吞吐量,增加了系统开销:因为某些进程的执行可能会被无限推迟。
破坏循环等待条件(有序资源使用法)
每个进程只能按递增顺序申请资源,即进程申请了序号为 8 的资源后,下次只能申请序号为 9 或以上资源。 如果进程需要同一资源类型的多个实例(也就是序号相同的资源),则必须对它们一起进行申请。 如果进程后面又想申请序号低的资源(比如5),那就必须把现在拥有的序号为5及其以上的资源全部释放。
序号必须相对稳定,这就限制了新设备的增加。 如果作业使用各类资源的顺序与系统规定的递增顺序不符合的话,就会造成资源的浪费。 按规定次序申请资源的方法会限制用户简单、自主地编程。
唯一性:自增主键确保每行记录都有一个唯一的标识符。这有助于确保数据的完整性,防止重复插入相同的记录。 快速查找:自增主键是一个整数,通常按顺序递增。这使得在表中进行快速查找和排序变得更加高效,因为数据库引擎可以更容易地使用二进制搜索等算法。 索引:通常,自增主键会自动创建一个索引,这进一步提高了查询性能。索引可以加速检索特定值的行,因此自增主键可以显著提高查询效率。 连接表:自增主键通常用作连接表(join)的依据,帮助将多个表中的数据关联在一起。这对于复杂的查询和数据分析非常有用。 简化数据访问:自增主键为开发人员提供了一种简单的方式来访问和修改表中的记录。通过使用唯一的自增值,开发人员可以更容易地编写SQL查询,执行插入、更新和删除操作。 与ORM框架兼容性:许多对象关系映射(ORM)框架和应用程序开发工具支持自增主键,因此使用自增主键可以简化应用程序的开发和维护过程。
数据筛选:范围查询允许您根据某个特定的范围条件来筛选数据。这意味着您可以轻松地检索满足特定条件的记录,而无需检索整个数据集。 精确性:范围查询可以用于查找符合精确条件的记录,例如在某个日期范围内的订单、在某个价格范围内的产品等。这有助于确保您获取准确的数据。 性能优化:使用索引,数据库可以快速执行范围查询,特别是当范围条件与索引字段匹配时。这可以显著提高查询性能,减少查询时间。 数据分析:范围查询对于数据分析非常有用。例如,您可以使用范围查询来查找某个时间段内的销售总额、某个地理区域内的用户数等。 灵活性:范围查询可以适用于多种数据类型和领域,从日期和数字到文本和地理位置数据。这使得它们在各种应用程序中都能够发挥作用。 高级过滤:范围查询可以用于高级过滤,例如查找某个时间段内超过特定阈值的事件、查找某个地理区域内的犯罪率高于平均水平的地点等。 数据导出和报告:范围查询的结果通常可以用于生成报告或导出数据,以供进一步分析或共享给其他人使用。
不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。 存储引擎不能使用索引范围条件右边的列。 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *。 mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描。 is null,is not null也无法使用索引 ---- 此处存在疑问,经测试确实可以使用,ref和const等级,并不是all。 like以通配符开头(’%abc…’)mysql索引失效会变成全表扫描的操作。
对于单键索引,尽量选择针对当前query过滤性更好的索引。 在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。 在选择组合索引的时候,尽量选择可以能够包含当前query中的where子句中更多字段的索引。 尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的。
事务隔离级别设置:在数据库中,可以设置事务的隔离级别来控制脏读和幻读的发生。常见的隔离级别包括 READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。不同的隔离级别提供不同的数据一致性和并发控制。通常,更高的隔离级别能够解决更多的并发问题,但也可能导致性能下降。 使用事务:将读操作和写操作封装在事务中,以确保数据的一致性。事务可以通过开始事务、执行一系列数据库操作,然后提交事务或者回滚事务来控制数据的访问。 悲观锁:悲观锁是一种强制性的锁机制,用于控制并发访问。它会在读或写数据之前,明确地锁定数据,以防止其他事务访问相同的数据。悲观锁通常需要显式地编写锁定和解锁逻辑。 乐观锁:乐观锁是一种更轻量级的并发控制方式。它不会显式锁定数据,而是在更新数据时检查数据是否被其他事务修改过。如果数据已经被修改,更新操作将失败。乐观锁通常使用版本号或时间戳来实现。 使用索引:在一些情况下,通过合理设计数据库表的索引,可以减少锁竞争,提高并发性,从而减少脏读和幻读的发生。 合理的业务逻辑设计:在应用程序的业务逻辑中,需要仔细考虑事务的边界和范围。合理的事务设计可以降低脏读和幻读的风险。 数据库引擎优化:使用具有良好并发控制机制的数据库引擎,如InnoDB,可以降低脏读和幻读的风险。这些引擎提供了事务支持和各种隔离级别。 监控和调优:定期监控数据库性能,识别潜在的并发问题,并对数据库进行性能调优是解决脏读和幻读问题的重要步骤。
作用:撤销日志用于记录事务中对数据库的修改,以便在事务回滚或发生故障时恢复数据到之前的状态。它主要用于保证事务的一致性和隔离性。 内容:撤销日志包含了在事务执行期间对数据进行的修改的逆操作,以便将数据还原到事务开始前的状态。 使用场景:撤销日志通常用于支持事务回滚、MVCC(多版本并发控制)和读一致性快照的生成。 持久性:撤销日志通常存储在磁盘上,并在事务提交后清除。
作用:重做日志用于记录事务对数据库的修改,以便在数据库崩溃或故障恢复时,重新应用这些修改,确保数据的持久性和完整性。 内容:重做日志包含了事务对数据的修改操作,而不是逆操作,以便能够重新执行这些修改。 使用场景:重做日志主要用于数据库的恢复和崩溃恢复,以确保在故障后数据不会丢失或损坏。 持久性:重做日志通常在事务提交时首先存储在磁盘上,然后在后台异步刷新到磁盘以提高性能。这确保了即使在数据库崩溃时,也可以使用重做日志来恢复数据。
当数据库崩溃时,数据库管理系统会在恢复模式下启动。在此模式下,系统会检查数据库的日志文件,尤其是重做日志。 首先,系统会检查重做日志,以确定哪些事务的修改尚未被应用到数据文件。它会重新应用这些修改,以确保数据的持久性。 接下来,系统会检查撤销日志,以确定是否有未完成的事务。如果有未完成的事务,系统会使用撤销日志来回滚这些事务,以确保数据的一致性。 一旦数据库恢复完成,系统会正常启动,允许用户再次访问数据库。
Redo Log(重做日志):重做日志记录了在事务提交之前对数据库所做的修改操作。这包括了插入、更新和删除等操作。当数据库崩溃时,它可能会导致某些事务的修改尚未持久化到磁盘上的数据文件。在这种情况下,数据库系统可以使用重做日志来重新应用这些修改,将数据还原到事务提交时的状态。 Undo Log(撤销日志):撤销日志记录了在事务执行期间对数据库的修改的逆操作。这意味着它包含了事务的回滚信息。如果在崩溃时某些事务尚未完成,或者它们的修改未能持久化,那么数据库系统可以使用撤销日志来撤销这些事务的操作,将数据还原到它们开始执行前的状态。
内存缓存和磁盘存储:在数据库系统中,数据通常会首先被加载到内存中,以提高读取和写入操作的性能。内存中的数据可以更快地访问,但它们不是永久存储的。相反,数据必须定期刷写(写回)到磁盘上的持久存储(通常是数据文件)以确保数据的持久性。 刷盘操作:刷盘机制是指将内存中的脏数据(已被修改但尚未写回磁盘的数据)刷写到磁盘上的过程。这通常是由数据库管理系统自动执行的,并且会在以下情况下触发: 事务提交:当事务成功提交时,数据库会将该事务中的所有修改操作刷写到磁盘,以确保数据的持久性。 定期检查点:数据库系统会定期执行检查点操作,将内存中的数据刷写到磁盘。检查点是为了减少数据库崩溃后的恢复时间。 内存不足:如果内存中的脏数据达到一定阈值,数据库系统可能会触发刷盘操作,以释放内存并确保数据的持久性。 刷盘策略:刷盘操作的频率和策略可以根据数据库系统的配置和性能需求进行调整。常见的刷盘策略包括: 同步刷盘:每次事务提交都会同步刷写数据到磁盘。这可以确保数据的持久性,但可能会降低性能,因为磁盘写入是相对较慢的操作。 异步刷盘:数据库系统可以使用异步刷盘策略,将刷盘操作延迟到后台进行,以提高性能。但这种策略可能会在数据库崩溃时导致少量数据的丢失。 混合刷盘:一些数据库系统使用混合策略,结合了同步和异步刷盘,以平衡性能和数据保护。 刷盘性能和可靠性权衡:刷盘机制的设计涉及性能和数据可靠性之间的权衡。更频繁的刷盘可以提高数据可靠性,但可能会降低性能。较少的刷盘可以提高性能,但可能会增加数据丢失的风险。数据库管理员和开发人员需要根据应用程序的需求和重要性来选择适当的刷盘策略。
内存存储:Redis 将数据存储在内存中,这使得数据访问非常快速。因为内存的读写速度比磁盘快得多,所以 Redis 能够在毫秒级别内响应请求。 非阻塞 I/O:Redis 使用非阻塞的 I/O 操作,充分利用了现代操作系统的异步 I/O 特性。这意味着 Redis 可以在等待磁盘操作完成时继续处理其他请求,而不会被阻塞。 事件驱动:Redis 使用事件驱动的方式来处理客户端请求。它使用单个线程来监听和处理多个客户端连接,而不需要为每个连接创建一个新线程。这降低了线程管理开销,使 Redis 更加高效。 精心优化的数据结构:Redis 内置了各种高效的数据结构,如哈希表、有序集合和位图等。这些数据结构经过精心优化,以提高性能和减少内存消耗。 持久化选项:Redis 提供了多种持久化选项,包括快照(snapshot)和追加日志文件(append-only file),这些选项允许用户根据需求权衡性能和数据安全。 单一路径执行:Redis 避免了复杂的锁和多线程竞争,因为它在单线程中按顺序执行命令,这减少了竞争条件和锁带来的开销。 原生支持多种数据结构:Redis 不仅仅是一个键值存储,它支持多种数据结构,如字符串、列表、哈希、集合、有序集合等。这种多样性使 Redis 可以应对不同的数据访问模式。
原子性(Atomicity):Redis 支持单个命令的原子性,这意味着单个命令要么完全执行,要么不执行。但 Redis 并没有内置的跨命令事务支持,也就是说,如果你需要执行多个命令来实现一个复杂的事务,Redis 无法保证这些命令的原子性。 一致性(Consistency):Redis 是一个单节点存储系统,不支持分布式事务。因此,在分布式环境中,Redis 无法提供全局一致性。此外,Redis 在某些情况下可能会采用最终一致性而不是强一致性。 隔离性(Isolation):Redis 的默认隔离级别是 READ COMMITTED,这是一个较低的隔离级别,可能导致一些并发问题,如脏读、不可重复读和幻读。虽然 Redis 支持 MULTI/EXEC 命令来实现事务,但默认情况下它不提供串行化的隔离级别。 持久性(Durability):Redis 默认情况下将数据存储在内存中,并使用快照(snapshot)和追加日志文件(append-only file)等持久化选项来将数据写入磁盘。虽然 Redis 可以提供持久性,但这是一个可配置选项,可能会影响性能。因此,在极端情况下,如果 Redis 内存中的数据尚未写入磁盘,可能会在发生故障时丢失数据。
配置主服务器:在主从复制架构中,首先需要配置主服务器。主服务器包含要被复制的数据,负责处理写操作和发送数据变更给从服务器。 配置从服务器:配置一个或多个从服务器,从服务器连接到主服务器,并请求数据复制。通常,从服务器会指定主服务器的地址和端口以及复制的数据集。 初始化数据复制:在从服务器首次连接到主服务器时,需要进行一次初始数据复制。主服务器会将数据发送给从服务器,使从服务器的数据与主服务器保持一致。 持续数据同步:一旦初始化完成,主服务器会将其数据的变更操作(写操作)记录到一个叫做 "二进制日志"(binlog)的文件中。从服务器定期轮询主服务器的二进制日志,将未复制的变更操作应用到自己的数据集中,以保持数据的同步。 监控和维护:需要定期监控主从服务器的状态,确保复制正常运行。如果出现故障或延迟,需要及时处理问题,以保证数据的一致性。
初始配置:当设置一个新的主从复制架构时,需要手动指定一个主服务器。 主服务器故障:如果主服务器发生故障或不可用,需要选择一个新的主服务器。 手动切换:在某些情况下,管理员可能会手动切换主服务器,例如进行维护或升级操作。

每分钟都去查询数据库,数据库的压力比较大。 有一定的延迟。

#include <iostream>#include <vector>void merge(std::vector<int>& nums1, int m, std::vector<int>& nums2, int n) {int i = m - 1; // 指向 nums1 中的最后一个元素int j = n - 1; // 指向 nums2 中的最后一个元素int k = m + n - 1; // 指向合并后的数组的最后一个位置while (i >= 0 && j >= 0) {if (nums1[i] >= nums2[j]) {nums1[k] = nums1[i];i--;} else {nums1[k] = nums2[j];j--;}k--;}// 如果 nums2 中还有剩余元素,将其复制到 nums1 中while (j >= 0) {nums1[k] = nums2[j];j--;k--;}}int main() {std::vector<int> nums1 = {1, 2, 3, 0, 0, 0}; // 有序数组 nums1std::vector<int> nums2 = {2, 5, 6}; // 有序数组 nums2int m = 3; // nums1 中的元素数目int n = 3; // nums2 中的元素数目merge(nums1, m, nums2, n);std::cout << "合并后的数组 nums1: ";for (int num : nums1) {std::cout << num << " ";}std::cout << std::endl;return 0;}

以上就是今天要讲的所有内容哈,图文以及代码可供大家思考,有不懂的也可以私我一起探讨(别抬杠就行)。
文章转载自阿Q正砖,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




