第七篇:并发-恢复机制

目录

复习

ACID 属性

动机

假设

缓冲区缓存(池)

数据库系统的主要组成部分

​ 处理缓冲池(缓存)

更多关于窃取和强制

基本想法:日志记录

预写日志 (WAL)

WAL 和日志

日志记录

其他日志相关状态

事务Xact 的正常执行

检查点

大图:什么存储在哪里

简单事务中止

事务中止示例

事务提交

故障恢复:大图

恢复:分析阶段

恢复:重做阶段

恢复:UNDO 阶段

其他崩溃问题

日志/恢复总结

分布式事务处理中的原子性

两阶段提交协议


复习

ACID 属性

❖ 原子性:Xact 中的所有动作都发生,或者不发生。
❖ 一致性:如果每个 Xact 是一致的,并且 DB 开始一致,则它最终一致。
❖ 隔离:一个 Xact 的执行与其他 Xact 的执行隔离。
❖ 持久性:如果 Xact 提交,其效果将持续存在。

❖ 恢复管理器(Recovery manager)保证原子性和持久性。

动机

❖ 原子性:
– 交易可能会中止(“回滚”)。 例如。 T6
❖ 持久性:
– 如果 DBMS 停止运行怎么办? (原因?)

❖ 系统重启后的期望行为:
– T1、T2 和 T3 应该是耐用持久的,因为它们是在崩溃前提交的。
– T4、T5、T6 应中止(未见效果)。

假设

❖ 并发控制生效。
– 特别是严格的 2PL(两段锁定)。
❖ 更新正在“就地”进行。
– 即数据在磁盘上被覆盖(删除)。
❖ 保证原子性和持久性的简单方案?

缓冲区缓存(池)

1. 数据存储在磁盘上
2. 读取数据项需要从磁盘到包含该项目的内存读取整页数据(通常为 4K 或 8K 字节的数据,具体取决于页面大小)。

3. 修改数据项需要将整个页面从磁盘读取到包含该项目的内存中,修改内存中的项目并将整个页面写入磁盘。

4. 步骤 2 和 3 可能非常昂贵,我们可以通过在内存中存储尽可能多的磁盘页面(缓冲区缓存)来最小化磁盘读取和写入的次数——这意味着如果感兴趣的磁盘页面总是在缓冲区缓存中检查, 如果不将关联的页面复制到缓冲区缓存就执行必要的操作。

5. 当缓冲区缓存已满时,我们需要从缓冲区缓存中驱逐一些页面,以便从磁盘中获取所需的页面。

6. 驱逐需要确保没有其他人正在使用该页面,并且任何修改过的页面都应该被复制到磁盘。

7. 由于多个事务同时执行,因此需要使用锁存器的附加锁定过程。 这些锁存器仅在操作期间使用(例如 READ/WRITE)并且可以立即释放,这与必须保持锁定直到事务结束的记录锁不同。

❖ 修复(pageid)
– 如果页面不在缓冲区缓存中,则从磁盘读取页面到缓冲区缓存中
– 由于事务正在访问内容,因此无法从缓冲区缓存中删除固定页面

❖ unfix(pageid)
– 该页面未被事务使用,就 unfix 调用事务而言,该页面可以被驱逐。 (我们需要检查以确保没有其他人想要该页面,然后才能将其驱逐)

数据库系统的主要组成部分

❖ 缓冲区管理器

从数据库按需加载到缓冲区

锁管理器

按需加锁

 处理缓冲池(缓存)

❖ 在提交时强制写入磁盘?
– 响应时间短。
– 但提供耐用性/持久性。

❖ 不强制,即使提交后也不修改磁盘上的数据,尽可能将页面留在内存中。
– 提高响应时间和效率,因为许多读取和更新可以在主内存中而不是在磁盘上进行。
- 持久性成为问题,因为如果发生崩溃,更新可能会丢失

❖ 从未提交的 Xacts 中窃取缓冲池帧?
– 如果不是,则吞吐量较差。
– 如果是这样,我们如何确保原子性?

更多关于窃取和强制

❖ STEAL(为什么很难执行原子性)
– 窃取 帧F:F 中的当前页(比如 P)被写入磁盘; 一些 Xact 锁定 P。
◆ 如果锁定P 的Xact 中止怎么办?
◆ 必须记住窃取时P 的旧值(以支持撤销对页P 的写入)。

❖ NO FORCE(为什么执行 Durability 很难)
– 如果系统在修改页面写入磁盘之前崩溃怎么办?
– 在提交时,在方便的地方,尽可能少写,以支持 REDOing 修改。

基本想法:日志记录

❖ 在日志中记录每次更新的 REDO(新值)和 UNDO(旧值)信息。
– 顺序写入日志(将其放在单独的磁盘上)。
– 写入日志的最少信息 (diff),因此多个更新在单个日志页面。

❖ 日志:REDO/UNDO 操作的有序列表
– 日志记录包含:
<XID、pageID、偏移量、长度、旧数据、新数据>
– 以及其他控制信息(我们很快就会看到)。

预写日志 (WAL)

❖ 预写日志协议:
1. 必须在相应的数据页到达磁盘(被盗)之前强制更新具有旧值和新值的日志记录。
2. 必须在提交前将所有日志记录写入磁盘(强制)以用于 Xact。

❖ 1. 保证原子性,因为我们可以撤消由中止事务执行的更新并重做那些已提交事务的更新。
❖ 2. 保证耐用性。
❖ 日志记录(和恢复!)究竟是如何完成的? – 我们研究 ARIES 算法。

WAL 和日志

❖ 每条日志记录都有一个唯一的日志序列号 (LSN)。
– LSN 一直在增加。

❖ 每个数据页包含一个pageLSN。
– 更新该页面的最新日志记录的 LSN。

❖ 系统跟踪flushedLSN。
– 到目前为止已刷新最大 LSN 。

❖ WAL:在页面写入磁盘之前确保
pageLSN <= flushedLSN

如下图,此时无法将页面写入磁盘

如下图,此时可以将页面写入磁盘

日志记录

 

日志记录字段可能的日志记录类型(对应左侧的type)
prevLSN
XID
type
length
pageID
offset
before-image
after-image

❖ Update
❖ Commit
❖ Abort
❖ End (signifies end of commit or abort)

表示提交结束或中止结束
❖ Compensation Log Records (CLRs)

补偿日志记录
– for UNDO actions

其他日志相关状态

❖ 事务表:
– 每个活动的 Xact 一个条目。
– 包含 XID、状态(运行/提交/中止)和 lastLSN。

❖ 脏页表:
– 缓冲池中每个脏页一个条目。
– 包含 recLSN -- 日志记录的 LSN,自从从磁盘加载到缓冲区缓存后,首先导致页面变脏的日志记录的 LSN。

事务Xact 的正常执行

❖ 一系列读写,然后是提交或中止。
        – 我们假设在磁盘上写操作是原子的。
            ◆ 在实践中,处理非原子写入的附加细节。 我们之前讨论过如何做到这一点。

❖ 严格的 2PL两段锁。
❖ STEAL、NO-FORCE 缓冲区管理,带有预写日志WAL。

检查点

❖ DBMS 会定期创建检查点,以最大限度地减少系统崩溃时恢复所需的时间。 写入日志:

– 开始检查点记录:指示 检查点 何时开始。
– 结束检查点记录:包含当前 Xact 事务表和脏页表。 这是一个“模糊检查点”:

    ◆ 其他Xacts 继续运行; 所以这些表仅在开始检查点记录时准确。
    ◆ 不尝试将脏页强制写入磁盘; 检查点的有效性受到对脏页的最旧未写入更改的限制。 (因此,定期将脏页刷新到磁盘是个好主意!)

– 将 检查点 记录的 LSN 存储在安全的地方(主记录)。

大图:什么存储在哪里

LogDBRAM

LogRecords(日志记录)

prevLSN
XID
type
length
pageID
offset
before-image
after-image

master record(主记录)

Data pages(数据页)
each
with a
pageLSN
Xact Table(事务表)
lastLSN
status
Dirty Page Table(脏页表)
recLSN
flushedLSN

简单事务中止

❖ 现在,考虑 Xact 事务的显式中止。
    – 不涉及故障。

❖ 我们要以相反的顺序“回放”日志,UNDOing 更新。
    – 从 Xact 表中获取 Xact 的 lastLSN。
    – 可以通过 prevLSN 字段向后跟踪日志记录链。
    – 在开始 UNDO 之前,写入 Abort 日志记录。
       ◆ 用于在UNDO 期间从崩溃中恢复!

❖ 要执行UNDO,必须有数据锁!
    - 没问题!

❖ 在恢复一个页的旧值之前,写一个 CLR(补偿日志记录):
    – 您在撤消时继续记录!!
    – CLR 有一个额外的字段:undonextLSN
        ◆ 指向下一个要撤销的 LSN(即我们当前正在撤销的记录的 prevLSN)。
    – CLR 永远不会撤消(但在重复历史时它们可能会重做:保证原子性!)

❖ 在 UNDO 结束时,写入“结束”日志记录。

事务中止示例

事务提交

❖ 将提交记录写入日志。
❖ 刷新到 Xact 的 lastLSN 的所有日志记录。
    – 保证flushedLSN >= lastLSN。
    – 请注意,日志刷新是顺序的、同步写入到磁盘 –(写入磁盘的速度非常快)。
    – 每个日志页有许多日志记录 –(由于多次写入而非常高效)。

❖ Commit() 提交返回。
❖ 将结束记录写入日志。

故障恢复:大图

❖ 从检查点开始(通过主记录找到)。

❖ 三阶段。 需要:
    – 找出自检查点以来提交的 Xact,哪些失败(分析)。
    – 重做所有动作。
        ◆(重复历史)
    – 失败的 Xacts 的 UNDO 效果。

恢复:分析阶段

❖ 在检查点重建状态。
    – 通过 end_checkpoint(最后的检查点) 记录。

❖ 从检查点向前扫描日志。

    – 结束记录:从 Xact 事务表中删除 Xact。
    – 其他记录:将 Xact 添加到 Xact 表,设置 lastLSN=LSN,在提交时更改 Xact 状态。
    – 更新记录:如果 P 不在脏页表中,
        ◆ 将 P 添加到 D.P.T.脏页表,设置其 recLSN=LSN。

恢复:重做阶段

❖ 我们重复历史以重建崩溃时的状态:
    – 重新应用所有更新(即使是中止的 Xact!),重做 CLR(补偿日志记录)。

❖ 从 D.P.T. 中包含最小 recLSN 的 log rec 向前扫描。 对于每个 CLR 或更新日志 recLSN,重做操作,除非:
    – 受影响的页面不在脏页表中,或
    – 受影响的页面在 D.P.T. 脏页表中,但 recLSN > LSN,或
    – pageLSN(在数据库中)>=LSN。

❖ 重做一个动作:
    – 重新应用记录的操作。
    – 将 pageLSN 设置为 LSN。 没有额外的日志记录!

恢复:UNDO 阶段

ToUndo={ l | l 是“失败者”Xact 事务的最后一个 LSN}
我们可以从 Xtable 形成这个列表。

重复:
    – 在 ToUndo 中选择最大的 LSN。
    – 如果这个 LSN 是一个 CLR 并且 undonextLSN==NULL
        ◆ 为这个Xact 写一个结束记录。
    – 如果这个 LSN 是一个 CLR,并且 undonextLSN != NULL
        ◆ 将undonextLSN 添加到ToUndo
        ◆ (问:其他 CLR 会发生什么情况?)
    – 否则此 LSN 是更新。 撤消更新,编写 CLR,将 prevLSN 添加到 ToUndo。
直到 ToUndo 为空。

恢复示例

示例:重启时崩溃!

其他崩溃问题

❖ 如果系统在分析过程中崩溃会怎样? 在重做期间?
❖ 你如何限制REDO的工作量?
    – 在后台异步刷新。
    – 观看“热点”!
❖ 如何限制 UNDO 的工作量?
    – 避免长时间运行的 Xact事务。

日志/恢复总结

❖ 恢复管理器保证原子性和持久性。
❖ 使用 WAL 允许 STEAL/NO-FORCE 而不牺牲正确性。
❖ LSN 识别日志记录; 每个交易链接到反向链(通过 prevLSN)。
❖ pageLSN 允许比较数据页和日志记录。

❖ 检查点:一种限制恢复时要扫描的日志量的快速方法。
❖ 恢复工作分 3 个阶段:
– 分析:从检查点转发。
– 重做:从最旧的 recLSN 转发。
– 撤消:从末尾向后倒退到崩溃时存活的最旧 Xact 的第一个 LSN。
❖ 在撤消时,写入 CLR。
❖ 重做“重复历史”:简化逻辑!

分布式事务处理中的原子性

两阶段提交协议(2PC)有助于在分布式事务处理中实现原子性

两阶段提交协议

– 协调者或参与者可以中止交易

  • 如果参与者中止,它必须通知协调员
  • 如果参与者在超时时间内没有响应,协调器将中止

– 如果中止,协调器要求所有参与者回滚
– 如果中止,中止日志将被强制写入协调器和所有参与者的磁盘

OK,今天的内容就到这里告一段落,基本这一部分我想要讲的东西也差不多了,后续可能会针对后面几篇章节较为繁琐抽象的概念进行细节或者专题式的讲解,敬请期待哟!谢谢!有问题还是欢迎随时评论交流!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
第1部分概述 1 1 交易型系统设计的一些原则 2 1.1 高并发原则 3 1.1.1 无状态 3 1.1.2 拆分 3 1.1.3 服务化 4 1.1.4 消息队列 4 1.1.5 数据异构 6 1.1.6 缓存银弹 7 1.1.7 并发化 9 1.2 高可用原则 10 1.2.1 降级 10 1.2.2 限流 11 1.2.3 切流量 12 1.2.4 可回滚 12 1.3 业务设计原则 12 1.3.1 防重设计 13 1.3.2 幂等设计 13 1.3.3 流程可定义 13 1.3.4 状态与状态机 13 1.3.5 后台系统操作可反馈 14 1.3.6 后台系统审批化 14 1.3.7 文档和注释 14 1.3.8 备份 14 1.4 总结 14 第2部分高可用 17 2 负载均衡与反向代理 18 2.1 upstream配置 20 2.2 负载均衡算法 21 2.3 失败重试 23 2.4 健康检查 24 2.4.1 TCP心跳检查 24 2.4.2 HTTP心跳检查 25 2.5 其他配置 25 2.5.1 域名上游服务器 25 2.5.2 备份上游服务器 26 2.5.3 不可用上游服务器 26 2.6 长连接 26 2.7 HTTP反向代理示例 29 2.8 HTTP动态负载均衡 30 2.8.1 Consul+Consul-template 31 2.8.2 Consul+OpenResty 35 2.9 Nginx四层负载均衡 39 2.9.1 静态负载均衡 39 2.9.2 动态负载均衡 41 参考资料 42 3 隔离术 43 3.1 线程隔离 43 3.2 进程隔离 45 3.3 集群隔离 45 3.4 机房隔离 46 3.5 读写隔离 47 3.6 动静隔离 48 3.7 爬虫隔离 49 3.8 热点隔离 50 3.9 资源隔离 50 3.10 使用Hystrix实现隔离 51 3.10.1 Hystrix简介 51 3.10.2 隔离示例 52 3.11 基于Servlet 3实现请求隔离 56 3.11.1 请求解析和业务处理线程池分离 57 3.11.2 业务线程池隔离 58 3.11.3 业务线程池监控/运维/降级 58 3.11.4 如何使用Servlet 3异步化 59 3.11.5 一些Servlet 3异步化压测数据 64 4 限流详解 66 4.1 限流算法 67 4.1.1 令牌桶算法 67 4.1.2 漏桶算法 68 4.2 应用级限流 69 4.2.1 限流总并发/连接/请求数 69 4.2.2 限流总资源数 70 4.2.3 限流某个接口的总并发/请求数 70 4.2.4 限流某个接口的时间窗请求数 70 4.2.5 平滑限流某个接口的请求数 71 4.3 分布式限流 75 4.3.1 Redis+Lua实现 76 4.3.2 Nginx+Lua实现 77 4.4 接入层限流 78 4.4.1 ngx_http_limit_conn_module 78 4.4.2 ngx_http_limit_req_module 80 4.4.3 lua-resty-limit-traffic 88 4.5 节流 90 4.5.1 throttleFirst/throttleLast 90 4.5.2 throttleWithTimeout 91 参考资料 92 5 降级特技 93 5.1 降级预案 93 5.2 自动开关降级 95 5.2.1 超时降级 95 5.2.2 统计失败次数降级 95 5.2.3 故障降级 95 5.2.4 限流降级 95 5.3 人工开关降级 96 5.4 读服务降级 96 5.5 写服务降级 97 5.6 多级降级 98 5.7 配置中心 100 5.7.1 应用层API封装 100 5.7.2 配置文件实现开关配置 101 5.7.3 配置中心实现开关配置 102 5.8 使用Hystrix实现降级 106 5.9 使用Hystrix实现熔断 108 5.9.1 熔断机制实现 108 5.9.2 配置示例 112 5.9.3 采样统计 113 6 超时与重试机制 117 6.1 简介 117 6.2 代理层超时与重试 119 6.2.1 Nginx 119 6.2.2 Twemproxy 126 6.3 Web容器超时 127 6.4 中间件客户端超时与重试 127 6.5 数据库客户端超时 131 6.6 NoSQL客户端超时 134 6.7 业务超时 135 6.8 前端Ajax超时 135 6.9 总结 136 6.10 参考资料 137 7 回滚机制 139 7.1 事务回滚 139 7.2 代码库回滚 140 7.3 部署版本回滚 141 7.4 数据版本回滚 142 7.5 静态资源版本回滚 143 8 压测与预案 145 8.1 系统压测 145 8.1.1 线下压测 146 8.1.2 线上压测 146 8.2 系统优化和容灾 147 8.3 应急预案 148 第3部分高并发 153 9 应用级缓存 154 9.1 缓存简介 154 9.2 缓存命中率 155 9.3 缓存回收策略 155 9.3.1 基于空间 155 9.3.2 基于容量 155 9.3.3 基于时间 155 9.3.4 基于Java对象引用 156 9.3.5 回收算法 156 9.4 Java缓存类型 156 9.4.1 堆缓存 158 9.4.2 堆外缓存 162 9.4.3 磁盘缓存 162 9.4.4 分布式缓存 164 9.4.5 多级缓存 166 9.5 应用级缓存示例 167 9.5.1 多级缓存API封装 167 9.5.2 NULL Cache 170 9.5.3 强制获取最新数据 170 9.5.4 失败统计 171 9.5.5 延迟报警 171 9.6 缓存使用模式实践 172 9.6.1 Cache-Aside 173 9.6.2 Cache-As-SoR 174 9.6.3 Read-Through 174 9.6.4 Write-Through 176 9.6.5 Write-Behind 177 9.6.6 Copy Pattern 181 9.7 性能测试 181 9.8 参考资料 182 10 HTTP缓存 183 10.1 简介 183 10.2 HTTP缓存 184 10.2.1 Last-Modified 184 10.2.2 ETag 190 10.2.3 总结 192 10.3 HttpClient客户端缓存 192 10.3.1 主流程 195 10.3.2 清除无效缓存 195 10.3.3 查找缓存 196 10.3.4 缓存未命中 198 10.3.5 缓存命中 198 10.3.6 缓存内容陈旧需重新验证 202 10.3.7 缓存内容无效需重新执行请求 205 10.3.8 缓存响应 206 10.3.9 缓存头总结 207 10.4 Nginx HTTP缓存设置 208 10.4.1 expires 208 10.4.2 if-modified-since 209 10.4.3 nginx proxy_pass 209 10.5 Nginx代理层缓存 212 10.5.1 Nginx代理层缓存配置 212 10.5.2 清理缓存 215 10.6 一些经验 216 参考资料 217 11 多级缓存 218 11.1 多级缓存介绍 218 11.2 如何缓存数据 220 11.2.1 过期与不过期 220 11.2.2 维度化缓存与增量缓存 221 11.2.3 大Value缓存 221 11.2.4 热点缓存 221 11.3 分布式缓存与应用负载均衡 222 11.3.1 缓存分布式 222 11.3.2 应用负载均衡 222 11.4 热点数据与更新缓存 223 11.4.1 单机全量缓存+主从 223 11.4.2 分布式缓存+应用本地热点 224 11.5 更新缓存与原子性 225 11.6 缓存崩溃与快速修复 226 11.6.1 取模 226 11.6.2 一致性哈希 226 11.6.3 快速恢复 226 12 连接池线程池详解 227 12.1 数据库连接池 227 12.1.1 DBCP连接池配置 228 12.1.2 DBCP配置建议 233 12.1.3 数据库驱动超时实现 234 12.1.4 连接池使用的一些建议 235 12.2 HttpClient连接池 236 12.2.1 HttpClient 4.5.2配置 236 12.2.2 HttpClient连接池源码分析 240 12.2.3 HttpClient 4.2.3配置 241 12.2.4 问题示例 243 12.3 线程池 244 12.3.1 Java线程池 245 12.3.2 Tomcat线程池配置 248 13 异步并发实战 250 13.1 同步阻塞调用 251 13.2 异步Future 252 13.3 异步Callback 253 13.4 异步编排CompletableFuture 254 13.5 异步Web服务实现 257 13.6 请求缓存 259 13.7 请求合并 261 14 如何扩容 266 14.1 单体应用垂直扩容 267 14.2 单体应用水平扩容 267 14.3 应用拆分 268 14.4 数据库拆分 271 14.5 数据库分库分表示例 275 14.5.1 应用层还是中间件层 275 14.5.2 分库分表策略 277 14.5.3 使用sharding-jdbc分库分表 279 14.5.4 sharding-jdbc分库分表配置 279 14.5.5 使用sharding-jdbc读写分离 283 14.6 数据异构 284 14.6.1 查询维度异构 284 14.6.2 聚合数据异构 285 14.7 任务系统扩容 285 14.7.1 简单任务 285 14.7.2 分布式任务 287 14.7.3 Elastic-Job简介 287 14.7.4 Elastic-Job-Lite功能与架构 287 14.7.5 Elastic-Job-Lite示例 288 15 队列术 295 15.1 应用场景 295 15.2 缓冲队列 296 15.3 任务队列 297 15.4 消息队列 297 15.5 请求队列 299 15.6 数据总线队列 300 15.7 混合队列 301 15.8 其他队列 302 15.9 Disruptor+Redis队列 303 15.9.1 简介 303 15.9.2 XML配置 304 15.9.3 EventWorker 305 15.9.4 EventPublishThread 307 15.9.5 EventHandler 308 15.9.6 EventQueue 308 15.10 下单系统水平可扩展架构 311 15.10.1 下单服务 313 15.10.2 同步Worker 313 15.11 基于Canal实现数据异构 314 15.11.1 Mysql主从复制 315 15.11.2 Canal简介 316 15.11.3 Canal示例 318 第4部分案例 323 16 构建需求响应式亿级商品详情页 324 16.1 商品详情页是什么 324 16.2 商品详情页前端结构 325 16.3 我们的性能数据 327 16.4 单品页流量特点 327 16.5 单品页技术架构发展 327 16.5.1 架构1.0 328 16.5.2 架构2.0 328 16.5.3 架构3.0 330 16.6 详情页架构设计原则 332 16.6.1 数据闭环 332 16.6.2 数据维度化 333 16.6.3 拆分系统 334 16.6.4 Worker无状态化+任务化 334 16.6.5 异步化+并发化 335 16.6.6 多级缓存化 335 16.6.7 动态化 336 16.6.8 弹性化 336 16.6.9 降级开关 336 16.6.10 多机房多活 337 16.6.11 多种压测方案 338 16.7 遇到的一些坑和问题 339 16.7.1 SSD性能差 339 16.7.2 键值存储选型压测 340 16.7.3 数据量大时JIMDB同步不动 342 16.7.4 切换主从 342 16.7.5 分片配置 342 16.7.6 模板元数据存储HTML 342 16.7.7 库存接口访问量600w/分钟 343 16.7.8 微信接口调用量暴增 344 16.7.9 开启Nginx Proxy Cache性能不升反降 344 16.7.10 配送至读服务因依赖太多,响应时间偏慢 344 16.7.11 网络抖动时,返回502错误 346 16.7.12 机器流量太大 346 16.8 其他 347 17 京东商品详情页服务闭环实践 348 17.1 为什么需要统一服务 348 17.2 整体架构 349 17.3 一些架构思路和总结 350 17.3.1 种读服务架构模式 351 17.3.2 本地缓存 352 17.3.3 多级缓存 353 17.3.4 统一入口/服务闭环 354 17.4 引入Nginx接入层 354 17.4.1 数据校验/过滤逻辑前置 354 17.4.2 缓存前置 355 17.4.3 业务逻辑前置 355 17.4.4 降级开关前置 355 17.4.5 AB测试 356 17.4.6 灰度发布/流量切换 356 17.4.7 监控服务质量 356 17.4.8 限流 356 17.5 前端业务逻辑后置 356 17.6 前端接口服务端聚合 357 17.7 服务隔离 359 18 使用OpenResty开发高性能Web应用 360 18.1 OpenResty简介 361 18.1.1 Nginx优点 361 18.1.2 Lua的优点 361 18.1.3 什么是ngx_lua 361 18.1.4 开发环境 362 18.1.5 OpenResty生态 362 18.1.6 场景 362 18.2 基于OpenResty的常用架构模式 363 18.2.1 负载均衡 363 18.2.2 单机闭环 364 18.2.3 分布式闭环 367 18.2.4 接入网关 368 18.2.5 核心接入Nginx功能 369 18.2.6 业务Nginx功能 369 18.2.7 Web应用 370 18.3 如何使用OpenResty开发Web应用 371 18.3.1 项目搭建 371 18.3.2 启停脚本 372 18.3.3 配置文件 372 18.3.4 nginx.conf配置文件 373 18.3.5 Nginx项目配置文件 373 18.3.6 业务代码 374 18.3.7 模板 374 18.3.8 公共Lua库 375 18.3.9 功能开发 375 18.4 基于OpenResty的常用功能总结 375 18.5 一些问题 376 19 应用数据静态化架构高性能单页Web应用 377 19.1 整体架构 378 19.1.1 CMS系统 379 19.1.2 前端展示系统 380 19.1.3 控制系统 380 19.2 数据和模板动态化 381 19.3 多版本机制 381 19.4 异常问题 382 20 使用OpenResty开发Web服务 383 20.1 架构 383 20.2 单DB架构 384 20.2.1 DB+Cache/数据库读写分离架构 384 20.2.2 OpenResty+Local Redis+Mysql集群架构 385 20.2.3 OpenResty+Redis集群+Mysql集群架构 386 20.3 实现 387 20.3.1 后台逻辑 388 20.3.2 前台逻辑 388 20.3.3 项目搭建 389 20.3.4 Redis+Twemproxy配置 389 20.3.5 Mysql+Atlas配置 390 20.3.6 Java+Tomcat安装 394 20.3.7 Java+Tomcat逻辑开发 395 20.3.8 Nginx+Lua逻辑开发 401 21 使用OpenResty开发商品详情页 405 21.1 技术选型 407 21.2 核心流程 408 21.3 项目搭建 408 21.4 数据存储实现 410 21.4.1 商品基本信息SSDB集群配置 410 21.4.2 商品介绍SSDB集群配置 413 21.4.3 其他信息Redis配置 417 21.4.4 集群测试 418 21.4.5 Twemproxy配置 419 21.5 动态服务实现 422 21.5.1 项目搭建 422 21.5.2 项目依赖 422 21.5.3 核心代码 423 21.5.4 基本信息服务 424 21.5.5 商品介绍服务 426 21.5.6 其他信息服务 426 21.5.7 辅助工具 427 21.5.8 web.xml配置 428 21.5.9 打WAR包 428 21.5.10 配置Tomcat 428 21.5.11 测试 429 21.5.12 Nginx配置 429 21.5.13 绑定hosts测试 430 21.6 前端展示实现 430 21.6.1 基础组件 430 21.6.2 商品介绍 432 21.6.4 前端展示 434 21.6.5 测试 442
### 回答1: XXL-Job是一个轻量级分布式任务调度平台,具有易于集成和部署、稳定性高、功能丰富等特点。以下是一些XXL-Job的核心概念和功能: 1. 调度中心:XXL-Job调度中心是一个Web应用程序,用于管理任务的创建、修改、删除和执行。调度中心还提供了任务执行日志、调度统计和报警功能等。 2. 执行器:XXL-Job执行器是一个Java应用程序,用于接收和执行任务。执行器会向调度中心定时发送心跳以保持连接,并接收调度中心分配的任务进行执行。 3. 任务:XXL-Job任务是一个Java方法,可以通过执行器运行。任务可以通过调度中心进行管理,包括创建、修改、删除、暂停和恢复等操作。 4. 路由策略:XXL-Job提供了多种路由策略,例如按任务名、按分片等方式路由任务。 5. 分片:XXL-Job支持任务分片,将一个任务分成多个子任务并交给多个执行器并行执行。任务分片可以提高任务的并发度和执行效率。 6. 任务依赖:XXL-Job支持任务依赖,即一个任务可以依赖于另一个任务的执行结果。当依赖的任务执行完成后,才会开始执行依赖它的任务。 7. 报警:XXL-Job提供了报警功能,可以根据任务的执行结果和调度状态进行报警,例如执行失败、超时、错过调度等情况。 总的来说,XXL-Job是一个易于集成和部署、功能丰富的分布式任务调度平台,适用于各种任务调度场景。 ### 回答2: xxl-job是一个分布式任务调度框架,可以用来实现各种定时任务和异步任务的调度和执行。它提供了可视化的任务管理界面,以及强大的任务调度功能。 首先,xxl-job支持多种任务类型,包括简单的定时任务、固定延迟任务和CRON表达式任务。通过配置任务的执行策略和参数,可以灵活地满足各种任务需求。 其次,xxl-job提供了自动化的任务调度机制。它可以根据任务的执行情况,自动进行任务调度和失败重试。同时,还可以设置任务的失败告警机制,及时通知开发人员任务执行的失败情况。 第三,xxl-job提供了任务分片机制,可以将大任务划分为多个小任务,分配给不同的执行器进行执行。这样可以提高任务执行的效率和并发能力。 此外,xxl-job还支持任务的动态添加、暂停和恢复。开发人员可以通过API或者管理界面,实现任务的动态管理,无需重启应用就可以生效。 最后,xxl-job提供了丰富的管理界面,方便开发人员进行任务的配置和管理。可以通过界面查看和监控任务的执行情况,也可以查看任务的调度日志和错误日志,便于排查和分析问题。 综上所述,xxl-job是一个简单又全面的分布式任务调度框架。它不仅提供了多种任务类型和调度策略,还支持任务的动态管理和监控。在中级程序员面试中,如果能够熟练掌握xxl-job的使用和原理,将会给面试官留下良好的印象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值