故天将降大任于是人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为,所以动心忍性,曾益其所不能。 ——《孟子·告子下》之《生于忧患,死于安乐》
一、基础理论与语言
1.1 语言机制
解释型语言和编译型语言
编译型语言:使用专门的编译器,针对特定的平台,将高级语言源代码一次性的编译成可被该平台硬件执行的机器码,并包装成该平台所能识别的可执行性程序的格式。
在程序执行之前,需要一个专门的编译过程,把源代码编译成机器语言的文件,如 exe 格式的文件。以后要再运行时直接使用编译结果即可,如直接运行 exe 文件。因为只需编译一次,以后运行时不需要编译,所以编译型语言执行效率高。
总结
- 一次性的编译成平台相关的机器语言文件,运行时脱离开发环境,运行效率高
- 与特定平台相关,一般无法移植到其他平台
- Go、C、C++、Objective 等属于编译型语言
解释型语言:使用专门的解释器对高级语言源代码逐行解释成特定平台的机器码并立即执行。
不需要事先编译,其直接将源代码解释成机器码并立即执行,所以只要某一平台提供了相应的解释器即可运行该程序。
总结:
- 解释型语言每次运行都需要将源代码解释成机器码并执行,效率较低;
- 只要平台提供相应的解释器,就可以运行源代码,所以可以方便源程序移植;
- C#、PHP、Python 等属于解释型语言。
Java 是个特例,它需要编译,但是却没有直接编译为机器语言,而是编译为字节码,然后在 Java 虚拟机上以解释方式执行字节码。
指针和引用
- 有些语言有”指针”的概念,比如 C 语言;有些语言没有指针,取而代之的是”引用”,比如 Java、PHP。不管是”指针”还是”引用”,实际上它们的意思都是一样的,都是存储所指对象的内存地址。
- 将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针。或者反过来说,指针中存储了这个变量的内存地址,指向了这个变量,通过指针就能找到这个变量。
- 在编写链表代码的时候经常会有这样的代码:
p->next=q,这行代码是说 p 结点中的 next 指针存储了 q 结点的内存地址。 - 编写链表代码更复杂的经常会用到的:
p->next=p->next->next,这行代码表示 p 结点的 next 指针存储了 p 结点的下下一个结点的内存地址。
PHP:静态方法与
$this- php 中,静态方法随着类的加载而加载,优先于对象而存在。this 代表的是对象的引用,即为当前对象,静态方法是通过类调用的方法,不需要实例化,既然不需要实例化,就没有当前对象,既然没有当前对象,就不会有 this。
1.2 内存与并发模型
| 对比项 | 单工 | 半双工 | 全双工 |
|---|---|---|---|
| 数据方向 | 只能单向传输 | 双向,但同一时刻只能一个方向 | 双向,同一时刻可同时收发 |
| 是否需要方向切换 | 不需要 | 需要(收发轮流进行) | 不需要 |
| 信道数量 | 1 条 | 1 条(共享) | 2 条(逻辑上收发独立) |
| 效率 | 最低 | 中等,切换有开销 | 最高 |
| 生活类比 | 收音机广播 | 对讲机 | 打电话 |
| 协议举例 | — | HTTP/1.1(请求-响应交替)、集线器以太网 | HTTP/2 多路复用、WebSocket、全双工以太网 |
二、计算机网络与 Web 通讯
2.1 鉴权方案对比
| 方案 | 凭证形态 | 服务端是否有状态 | 能否主动失效 | 跨域支持 | 适用场景 |
|---|---|---|---|---|---|
| HTTP Basic | Authorization: Basic base64(user:pass) |
无 | 只能改密码 | 一般 | 内部工具、调试接口 |
| Session + Cookie | 服务端存 session,客户端存 SESSIONID |
有 | 可以,删 session 即可 | 需配置 CORS 携带凭证 | 传统单体 Web、同域名后台 |
| Token(JWT) | 自包含的签名 token | 无(自校验) | 需配合黑名单/短有效期 | 天然支持 | 前后端分离、多端接入 |
| OAuth 2.0 | 授权码 / access_token + refresh_token | 授权服务器有状态 | 可以,撤销 refresh_token | 支持 | 第三方登录、开放平台 |
| 双向 TLS | 客户端证书 | 无 | 吊销证书 | 支持 | 服务间高安全通信 |
JWT 结构:Header.Payload.Signature 三段点分。Header 声明算法,Payload 放声明(只做 Base64Url 编码,不是加密,不要放敏感信息),Signature 用密钥对前两段签名,服务端验签即完成认证。
2.2 单点登录(SSO)三种实现
| 方案 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 共享 Cookie(同主域) | 把 Cookie 的 domain 设为 .example.com,各子域共享 |
实现最简单 | 只能用于同一主域下 |
| 同域 CAS / 认证中心 | 未登录时重定向到认证中心,认证中心发 ticket,业务系统凭 ticket 换用户信息 | 跨域可用、标准成熟 | 需维护独立的认证中心 |
| 跨域 Token(JWT + 前端跳转) | 认证中心签发 token,各系统校验 token | 无需共享 session、天然分布式 | token 失效控制较麻烦 |
2.3 防盗链
| 手段 | 原理 | 能否绕过 |
|---|---|---|
校验 Referer |
判断请求来源域名是否在白名单内 | 可以,Referer 可伪造/被浏览器隐私策略清空 |
| 签名 URL(时间戳 + 密钥) | 链接带过期时间与签名,服务端验签 | 较难,但链接被转发后仍可在有效期内使用 |
| 时效性 token | 每次请求生成一次性 token | 较难 |
| 图片加水印 | 从内容层面标记来源 | 不能防下载,只能防冒用 |
nginx 限制 UA / IP |
拒绝非预期客户端 | 可以伪造 |
| 服务器端渲染校验 | 资源由服务端代理转发 | 较难 |
2.4 网站无法访问的排查路径
- 先判断是局部还是全局:换网络、换设备、用第三方拨测工具(如站长工具)测试。
- 域名解析:
nslookup/dig看是否解析到正确 IP,有无被污染或未备案导致解析被停。 - 运营商链路:
ping、traceroute看丢包与在哪一跳断。 - 端口与防火墙:
telnet ip 端口看端口是否通,云服务器检查安全组。 - 服务进程:
ps -ef、netstat -tlnp看进程是否存活、端口是否监听。 - Web 服务与后端:看 nginx 错误日志、后端应用日志,是否是 502/504。
- 资源层:数据库/Redis 是否连不上导致响应超时;磁盘是否写满。
- SSL 证书:是否过期、证书链是否完整。
- CDN 层:CDN 回源是否正常、缓存是否命中问题内容。
2.5 C10K 问题
- c10k 问题是同时处理大量客户端请求的网络 sockets 优化问题。c10k 用来命名并发处理 10k 连接的问题。人们一直研究 socket 服务优化,这其中有大量因素需要考虑来允许服务器支持大量服务端。这需要结合操作系统和 web 服务器软件的限制。根据服务的可提供范围以及操作系统和硬件限制如多进程能力,多线程模型或者单线程模型可以优先考虑。与此同时需要考虑内存管理(通常依赖操作系统),这些策略隐含了 I/O 管理的各个方面。
- 参考
| 模型 | 一个连接的成本 | 并发量级 | 代表实现 |
|---|---|---|---|
| 一个进程一个连接 | 进程栈 + 上下文切换开销大 | 百级 | 早期 Apache prefork |
| 一个线程一个连接 | 线程栈约 1MB | 千级 | Apache worker、Tomcat BIO |
| IO 多路复用 + 事件循环 | 一个连接仅少量内存 | 万级(C10K) | nginx、Redis、Node.js、Swoole |
| 协程 | 用户态调度,栈 KB 级 | 十万级(C100K) | Go goroutine、Swoole 协程、Java 虚拟线程 |
核心结论:瓶颈不在 CPU 而在「每连接的内存开销 + 上下文切换」,解决思路是用
epoll/kqueue事件驱动 + 非阻塞 IO,把”等 IO”这件事从”占着线程等”变成”注册回调”。
三、存储与中间件
- HDFS —— 一个易于扩展的分布式文件系统。原文
- Redis 缓存兜底方案设计 —— 原文
- Redis 实现防止重复提交 —— 原文
- Redis 高手 —— 原文
- 消息队列设计精要 —— 原文
- LMSTFY —— github.com/bitleak/lmstfy
3.1 缓存兜底方案
| 问题 | 现象 | 应对手段 |
|---|---|---|
| 缓存穿透 | 查询不存在的数据,请求每次都打到 DB | 缓存空值(设短过期时间)、布隆过滤器拦截、参数合法性校验 |
| 缓存击穿 | 热点 key 过期瞬间,大量请求同时压到 DB | 互斥锁/分布式锁重建缓存、逻辑过期不删 key、热点数据不过期 |
| 缓存雪崩 | 大批 key 同时过期,或 Redis 整体挂掉 | 过期时间加随机值打散、多级缓存、熔断降级、集群高可用 |
| 缓存与 DB 一致性 | 双写导致脏数据 | Cache Aside(先更新 DB 再删缓存)、延迟双删、订阅 binlog 异步刷新 |
| Redis 不可用 | 全部请求落到 DB,DB 被打挂 | 本地缓存兜底、限流、快速失败并返回降级数据 |
3.2 防止重复提交的几种做法
| 方案 | 实现 | 适用 |
|---|---|---|
| 前端禁用按钮 | 提交后置灰,配合 loading | 只防手抖,不防绕过 |
| Token 机制 | 进页面发一次性 token,提交时校验并删除(Redis DEL 返回 1 才放行) |
通用表单提交 |
| Redis 分布式锁 | SET key value NX PX 3000,拿到锁才处理业务 |
接口级防重 |
| 唯一索引 | DB 建唯一约束,重复插入直接报错 | 数据层面的最终兜底 |
| 幂等设计 | 用业务单号做幂等键,重复请求直接返回上次结果 | 支付、下单等强一致场景 |
SETNX+ 过期时间必须用一条命令(SET k v NX PX n),否则”设置锁”和”设置过期”之间宕机会造成死锁。
3.3 消息队列设计要点
| 关注点 | 说明 |
|---|---|
| 解耦 | 生产者只投递,不关心消费者有几个、是谁 |
| 异步 | 主链路只做必要校验,耗时逻辑异步化,缩短响应时间 |
| 削峰 | 突发流量先入队积压,消费者按自身能力匀速消费 |
| 消息丢失 | 生产端:确认机制(publisher confirm / acks);Broker 端:持久化 + 副本;消费端:手动 ACK |
| 重复消费 | 至少一次投递语义下必然重复,业务侧必须幂等(幂等键 + 去重表) |
| 顺序性 | 同一业务 key 路由到同一分区/队列,单分区内单线程消费 |
| 积压告警 | 监控队列深度与消费延迟,超过阈值告警 |
3.4 算法题
两个大数相加 —— 字符串模拟竖式加法,从低位向高位逐位相加并处理进位,时间复杂度 O(max(m,n))。原文
大文件小内存排序 —— 典型场景:一个 10GB 的文件,内存只有 1GB,要排序。
| 方案 | 做法 | 复杂度 | 适用 |
|---|---|---|---|
| 外部排序(归并) | 分块读到内存(如每次 100MB),块内快排后写回磁盘形成若干有序小文件;再对这些文件做 k 路归并输出 | O(n log n) | 全量有序输出(通用解) |
| 分桶 / 哈希分片 | 先按哈希把数据散成 N 个小文件(同一 key 落到同一文件),再逐个文件在内存里排序 | O(n) 均摊 | 找 Top K、找重复元素,不需要全量有序 |
| 位图 / 布隆过滤 | 只记录”是否存在”,用 bit 数组 | O(n) | 40 亿整数判存在性,空间可压到 512MB |
| 小顶堆 | 维护大小为 K 的堆,扫描一遍 | O(n log K) | 只求 Top K,内存 O(K) |
- 一秒内可以执行多少次 for 循环
| 语言/场景 | 量级 | 说明 |
|---|---|---|
| C / C++ 空循环 | 约 1×10⁸ ~ 1×10⁹ 次 | 取决于 CPU 主频、是否被编译器优化掉、循环体是否有内存访问 |
| Java 空循环(JIT 预热后) | 约 1×10⁸ ~ 5×10⁸ 次 | 受 JIT 优化与逃逸分析影响很大 |
| PHP 空循环 | 约 1×10⁷ ~ 5×10⁷ 次 | 解释执行,每次循环都有 opcode 派发开销 |
| Python 空循环 | 约 3×10⁷ 次 | CPython 解释器开销大,同样逻辑用 numpy/列表推导可快一个数量级 |
| JS(V8)空循环 | 约 1×10⁸ ~ 5×10⁸ 次 | JIT 优化后接近 Java |
- 实测要点:这个数字几乎没有意义——实际耗时由循环体决定。循环体内有一次内存访问,性能就可能降一个数量级;有系统调用或 IO,再降几个数量级。
- 正确做法是关心常数因子:减少循环内的方法调用、避免重复计算长度、把循环内不变的计算提到循环外、用局部变量缓存全局变量。
四、架构与分布式
4.1 Hadoop 生态组件
| 组件 | 定位 | 一句话说明 |
|---|---|---|
| HDFS | 分布式文件系统 | 存储层基础,NameNode 管元数据、DataNode 存数据块,默认 3 副本 |
| MapReduce | 批处理计算模型 | 把任务拆成 Map(映射)与 Reduce(归约)两阶段,适合离线大批量计算 |
| YARN | 资源调度 | 集群资源管理与任务调度层,让多计算框架共用一套资源 |
| Hive | 数仓 SQL 引擎 | 把 SQL 翻译成 MapReduce/Spark 任务,面向离线分析,延迟高但易用 |
| HBase | 列式 NoSQL 数据库 | 基于 HDFS 的高可靠、可扩展的 KV/列族存储,支持海量数据的随机读写 |
| ZooKeeper | 分布式协调 | 提供分布式锁、选主、配置管理、命名服务,是 Dubbo/HBase/Kafka 的公共依赖 |
| Kafka | 分布式消息队列 | 高吞吐发布-订阅,兼做日志采集与流式管道 |
| Spark | 内存计算引擎 | 基于 RDD/DataFrame,比 MapReduce 快一个数量级,涵盖批、流、SQL、ML |
| Kylin | OLAP 预计算 | 把多维分析预先打成 Cube,实现亚秒级查询响应 |
| Mahout | 机器学习库 | Hadoop 上的经典 ML 算法库,现多被 Spark MLlib 取代 |
| Dubbo | RPC 服务框架 | 面向 Java 的分布式服务治理框架,含注册发现、负载均衡、容错 |
| RPC | 远程过程调用 | 让调用远程方法像调用本地方法一样,屏蔽网络细节 |
4.2 架构演进路线图
1 | 单机 → 垂直拆分(按业务拆库拆应用) |
4.3 中间件
- 中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机 / 服务器的操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递。通过中间件,应用程序可以工作于多平台或 OS 环境。
| 类型 | 作用 | 典型产品 |
|---|---|---|
| 终端仿真 / 屏幕转换中间件 | 屏蔽不同终端的差异,统一接入 | Telnet 网关、终端模拟器 |
| 远程过程调用中间件 | 让跨进程/跨机器的调用像本地调用 | Dubbo、gRPC、Thrift、Feign |
| 数据库中间件 | 分库分表、读写分离、连接池 | ShardingSphere、MyCat、ProxySQL |
| 消息中间件 | 异步解耦、削峰、最终一致 | RabbitMQ、Kafka、RocketMQ、Pulsar |
| 交易中间件 | 保障分布式事务的一致性 | Tuxedo、Seata、XA |
| 对象中间件 | 跨语言的对象请求代理 | CORBA、DCOM |
4.4 中台
- 定义:中台是把各业务线重复建设的能力抽取、沉淀、标准化后,以「共享服务中心」的形式对外提供,让前台能快速复用而不是每次从零搭。核心是能力的复用与高效响应,而不是简单的技术分层。
- 与平台的区别:平台是纵向的技术支撑(如数据平台、监控平台),中台是横向的业务能力沉淀,必须能被多个前台业务复用。
| 中台类型 | 沉淀的能力 | 典型内容 |
|---|---|---|
| 业务中台 | 可复用的业务能力 | 用户中心、订单中心、商品中心、支付中心、权限中心 |
| 数据中台 | 数据的采集、治理与对外服务 | 数据仓库、指标口径统一、标签体系、数据 API |
| 技术中台 | 通用技术能力 | 微服务框架、消息队列、缓存、网关、CI/CD |
| 组织中台 | 组织与协同机制 | 共享服务中心的团队划分与考核机制 |
风险提示:中台不是万能药。业务差异大、迭代速度要求极高的团队强上中台,很容易变成”中台响应慢、前台绕开走”的局面。判断标准是能力是否真的在多条业务线被重复建设。
4.5 数据埋点
- 埋点分析,是网站分析的一种常用的数据采集方法,是数据采集领域(尤其是用户行为数据采集领域)的术语,指的是针对特定用户行为或事件进行捕获、处理和发送的相关技术及其实施过程,如用户某个 icon 点击次数、观看某个视频的时长等。
- 埋点的作用就是用来做用户动作行为分析的,即时有效的埋点可以为产品的下一步推广、实施、改进等做导向。
埋点方式对比:
| 方式 | 实现 | 优点 | 缺点 |
|---|---|---|---|
| 代码埋点(初级) | 在业务代码中显式调用上报 SDK | 数据精准、可带丰富业务参数 | 侵入性强、改动需发版、漏埋/错埋难发现 |
| 可视化埋点(中级) | 运营在页面上圈选元素,自动生成采集规则 | 无需开发介入、上线快 | 只能采通用事件(点击/曝光),复杂逻辑采不到 |
| 全埋点 / 无埋点(高级) | SDK 自动采集所有点击、页面浏览等事件 | 零侵入、可回溯补分析 | 数据量大、缺乏业务语义、需大量后端清洗 |
埋点规范要点:事件命名统一(模块_动作_对象)、参数口径统一且在数据字典中登记、区分「事件发生时间」与「上报时间」、带上用户标识与设备标识、做好版本号与渠道号,便于后续归因。
4.6 Web 架构(一个完整的技术选型全景)
- 服务器:基于 nginx 实现负载均衡
- 应用
- 基于 git+gitlab+jenkins 实现持续集成
- 基于 jira 实现需求收集、任务分配、bug 处理等
- 基于 cdn 实现图片、样式、js 等内容分发,提高响应速度
- 数据库
- 基于 mysql 主从实现读写分离和高可用
- 基于 redis 主从和哨兵机制等实现高并发和高可用
- 消息队列:基于 RabbitMQ 实现消息的异步处理和应用解耦
- 研发
- 基于前后分离开发实现快速开发迭代
- 基于常用设计模式提高研发效率和易于扩展
- 基于
psr*规范封装自定义包实现代码复用 - 基于 swoole 框架进行异步、网络、多线程、RPC 调用等
- 基于 Elasticsearch 实现全文检索和日志分析处理等
- 压测:基于
ab、jmeter等应用进行压力测试 - 监控
- 基于 shell 脚本实时监控异常接口请求并邮件通知处理
- 基于 ELK stack 实现日志分析平台
五、性能与优化
5.1 优化网站速度
- 总的方向:减少请求数、减少资源大小、找最快的服务器。
| 优化方向 | 具体手段 | 效果说明 |
|---|---|---|
| 减少请求数 | 合并 CSS/JS、CSS Sprite、内联小图标(base64) | HTTP/1.1 下并发受限,请求数直接影响首屏 |
| 减少资源大小 | 优化图片格式与尺寸、压缩 CSS/JS、开启 gzip/brotli | 传输体积是加载耗时的第一要素 |
| 利用缓存 | 强缓存(Cache-Control/Expires)+ 协商缓存(ETag/Last-Modified) |
二次访问近乎零请求 |
| 减少重定向 | 去掉多余的 301/302 跳转、统一带不带 www 的入口 |
每次重定向都多一次往返 |
| 静态资源分发 | 使用 CDN 存储静态资源 | 就近接入,降低 RTT |
| 减少 DNS 查询 | 减少不同域名数量、使用 dns-prefetch |
DNS 解析有几十到几百毫秒 |
| 首屏优化 | 关键 CSS 内联、JS 加 defer/async、图片懒加载、路由按需加载 |
让用户更快看到内容 |
| 协议升级 | 开启 HTTP/2 多路复用、启用 HTTPS + TLS 1.3 | 减少连接建立与队头阻塞 |
| 服务端 | 加缓存(Redis)、优化慢 SQL、加索引、上集群 | 缩短 TTFB |
六、工具与环境
6.1 命令行与终端
- vim:使用 vim 时,如果不小心按了
ctrl + s后,终端窗口就动不了了,只需按ctrl + q即可恢复正常。 - Windows Terminal, Console and Command-Line
- Cygwin
- Linux 下 $PATH 设置:查看 PATH
echo $PATH。以添加 mongodb server 为例:
| 修改方式 | 操作 | 生效方法 | 有效期 | 影响用户 |
|---|---|---|---|---|
| 临时修改 | export PATH=/usr/local/mongodb/bin:$PATH |
立即生效 | 仅当前终端窗口 | 仅当前用户 |
| 用户级 | 编辑 ~/.bashrc 追加 export PATH=...,再 source ~/.bashrc |
立即或重开终端 | 永久 | 仅当前用户 |
| 系统级 | 编辑 /etc/profile 追加 export PATH=... |
系统重启(或 source) |
永久 | 所有用户 |
| 系统级 | 编辑 /etc/environment,在 PATH="..." 中加入 :/usr/local/mongodb/bin |
系统重启 | 永久 | 所有用户 |
Linux 下切换用户提示
su: Authentication failure1
sudo passwd username #设置初始密码或更改密码
root 执行命令提示
Operation not permitted:chattr是用来更改文件属性的,lsattr可用来查看文件的属性,执行命令lsattr filename便可以看到当前文件的属性;当文件有 i 属性的文件是不能修改的,更不可被删除,即使是 root 用户也不可。既然知道了文件不能删除的原因是加了 i 属性,所以相应的解决方案就是把文件的 i 属性去除,然后再删除:chattr -i filename,然后再执行相应命令就好了。包管理工具对比
| 工具 | 所属生态 | 管理对象 | 是否自动解决依赖 | 常用命令 | 说明 |
|---|---|---|---|---|---|
| wget | 通用 | 任意网络文件 | 不涉及 | wget [选项] URL |
从网络自动下载文件的工具,支持 HTTP/HTTPS/FTP,可用 HTTP 代理。名称源于 World Wide Web 与 get |
| yum | RedHat 系 | rpm 包 | 是 | yum install/remove/update |
全称 Yellow dog Updater Modified,基于 RPM 的 Shell 前端包管理器,可自动处理依赖,一次安装所有依赖包 |
| rpm | RedHat 系 | rpm 包 | 否 | rpm -ivh xxx.rpm |
全称 Red-Hat Package Manager,是打包与安装工具,生成 .rpm 文件,与 dpkg 类似,已是 Linux 事实标准 |
| apt-get | Debian 系 | deb 包 | 是 | apt-get install/remove/update |
Advanced Package Tool,适用于 deb 包管理的系统,从软件仓库自动搜索、安装、升级、卸载 |
| dpkg | Debian 系 | deb 包 | 否 | dpkg -i xxx.deb |
Debian Packager 简写,Debian 系软件包管理器的基础(1993 年由 Ian Murdock 创建);上层工具如 APT 负责远程获取与依赖处理 |
| deb | Debian 系 | — | — | — | Debian 软件包格式的文件扩展名,因 Debra Murdock(Debian 创始人 Ian Murdock 的太太)得名 |
| easy_install | Python | PyPI 包 | 部分 | easy_install 包名 |
来自 PEAK(Python Enterprise Application Kit)的 setuptools 包,本质是调用 setuptools 安装模块 |
| pip | Python | PyPI 包 | 是 | pip install 包名 |
现代通用 Python 包管理工具,提供查找、下载、安装、卸载功能,是 easy_install 的改进版 |
记忆要点:RedHat 系 = rpm(底层)+ yum(上层);Debian 系 = dpkg(底层)+ apt(上层)。 底层工具只管安装单个包,上层工具负责仓库与依赖。
6.2 开发环境与依赖管理
Windows 下安装 composer
1
2
3方式1、下载 exe 文件安装
方式2、下载 composer.phar 文件
命令行执行:echo @php "%~dp0composer.phar" %*>composer.bat (php.exe 加入环境变量)msi 文件安装时提示 2502 / 2503:
cmd msiexec /package D:\xxxx.msi将源码编译为 dll:以 C/C++ 为例,源文件与头文件需要用导出宏标记,再交给编译器生成动态库。
- 第一步:在头文件里声明导出(Windows 需要
dllexport/dllimport,Linux 用__attribute__((visibility("default")))):
1
2
3
4
5
6
7
8
9
10
11
12// mylib.h
#ifdef _WIN32
# ifdef MYLIB_EXPORTS
# define MYLIB_API __declspec(dllexport)
# else
# define MYLIB_API __declspec(dllimport)
# endif
#else
# define MYLIB_API __attribute__((visibility("default")))
#endif
MYLIB_API int add(int a, int b);- 第二步:编译成动态库
- MinGW / GCC:
gcc -shared -o mylib.dll mylib.c -Wl,--out-implib,libmylib.a - MSVC:
cl /LD mylib.c /Fe:mylib.dll(/LD就是生成动态库) - Linux 生成
.so:gcc -shared -fPIC -o libmylib.so mylib.c - 第三步:调用方链接
- 隐式链接:编译时链接导入库
.lib/.a,运行时 dll 需在PATH或同目录 - 显式链接:
LoadLibrary+GetProcAddress运行时动态加载,适合插件化 - 第四步(PHP 场景):给 PHP 写扩展时,先生成扩展骨架
phpize && ./configure --with-php-config=... && make,产物在modules/*.so,再在php.ini里extension=xxx.so加载(注意加载顺序,见 6.3)。
- 第一步:在头文件里声明导出(Windows 需要
Windows 下安装虚拟机:以 VirtualBox / VMware Workstation 为例。
- 下载安装包(VirtualBox 免费,VMware Workstation Player 个人免费)
- 安装时勾选桥接网络驱动;安装完重启一次
- 新建虚拟机:分配 CPU 核心(不超过物理核数的一半)、内存(不超过物理内存的一半)、磁盘(建议 40GB 以上,动态分配)
- 网络模式选择:
| 模式 | 虚拟机 IP | 能否上网 | 外部能否访问虚拟机 | 适用场景 |
|---|---|---|---|---|
| 桥接(Bridged) | 与主机同网段的独立 IP | 能 | 能(等同局域网内一台机器) | 需要被局域网其他机器访问、做服务器测试 |
| NAT | 共享主机 IP | 能 | 需在主机做端口转发 | 只需上网、不想占用局域网 IP |
| 仅主机(Host-only) | 主机内网段的独立 IP | 不能 | 仅主机能访问 | 隔离的内网实验环境 |
| 内部网络(Internal) | 独立网段 | 不能 | 仅虚拟机之间互通 | 多机集群的隔离实验 |
- 安装完成后安装增强功能(VirtualBox Guest Additions / VMware Tools),以获得剪贴板共享、自适应分辨率、共享文件夹
- 开发场景建议:装上 VMware Tools 后配置共享文件夹,把代码目录挂在虚拟机里,用宿主机 IDE 编辑、虚拟机跑环境
- 增加 swap 空间(示例)
1 | sudo dd if=/dev/zero of=/swapfile bs=64M count=16 |
- 图形 API:OpenGL / DirectX / Canvas / WebGL / Unity3D
| 名称 | 层级 | 平台 | 语言绑定 | 用途与特点 |
|---|---|---|---|---|
| OpenGL | 图形 API(底层) | 跨平台 | C 接口,多语言可绑定 | 跨平台 3D 图形标准,只管画图不管窗口与输入;桌面端 OpenGL,移动端 OpenGL ES;其现代低开销定位已由 Vulkan 承接 |
| DirectX | 图形与多媒体 API 集合 | Windows / Xbox | C++ 为主 | 微软自家 API 家族,含 Direct3D(3D 渲染)、Direct2D(2D)、DirectCompute(GPU 计算)、DirectSound、DirectInput;性能控制更贴近硬件 |
| Canvas | 浏览器 2D 绘图 API | 浏览器 | JavaScript | <canvas> + getContext('2d'),用 JS 命令式绘制 2D 图形、图表、动画;2D 场景首选 |
| WebGL | 浏览器 3D 绘图 API | 浏览器 | JavaScript(GLSL 着色器) | OpenGL ES 的浏览器绑定,通过 getContext('webgl') 在 canvas 中做 GPU 加速的 3D 渲染;Three.js / Babylon.js 基于它封装 |
| Unity3D | 游戏引擎(上层) | 跨平台,可导出 Web | C# 脚本 | 一站式游戏/交互内容开发引擎,封装渲染、物理、动画、音频、资源管理;导出 Web 时底层编译为 WebAssembly + WebGL |
- 关系梳理:
OpenGL/DirectX是底层图形 API(直接和 GPU 打交道);Canvas/WebGL是浏览器对图形能力的两条路线(2D 用 Canvas,3D 用 WebGL);Unity3D是在底层 API 之上封装的引擎,让开发者不必直接写渲染管线。
6.3 PHP 环境排障
git@github.com: Permission denied (publickey)- 背景:
git config全局配置了公司的user.name和user.email,在练手项目中单独配置了自己的user.name和user.email。将自己本地代码推到 github 网上有各种教程,在此就不再赘述了。其中有一步配置 SSH-KEY 时一直提示git@github.com: Permission denied (publickey).,网上也搜了但都没有解决,直到遇见了它:ssh-add ~/.ssh/自定义的id_rsa,执行一下就好了!
- 背景:
git push origin master报failed to push some refs1
2
3
4
5
6failed to push some refs to 'git@github.com:liusirdotme/learngit.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.git因为我在 github 初始化仓库时勾选了 README,这样就导致远程仓库比本地多了一个文件。根据报错执行
pull origin master时报fatal: refusing to merge unrelated histories.然后接下来主角出场:git pull origin master --allow-unrelated-histories查看 Linux 系统上的 php 位数是 32 位还是 64 位
1
2
3file /usr/bin/php #替换成 php 可执行文件目录
输出:
/usr/bin/php: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=82ae48b988b1acf24ae08a575e58a8981d968a54, stripped其中
ELF 64-bit LSB shared object, x86-64就代表 php 是 64 位的。编译安装 phalcon 扩展,
make install之后make test报错1
2
3
4
5
6Warning: PHP Startup: Unable to load dynamic
library '/usr/local/src/cphalcon-phalcon-v2.0.13
/build/64bits/modules/phalcon.so' -
/usr/local/src/cphalcon-phalcon-v2.0.13
/build/64bits/modules/phalcon.so: undefined symbol:
php_json_decode_ex in Unknown on line 0问题原因:扩展加载顺序导致,正常情况下应先加载
json.so后加载phalcon.so解决方案:设置扩展加载优先权重
1
2
3在 php.d 文件夹添加 phalcon.ini,添加以下内容:
extension=phalcon.so
priority=100 #尽量大一点编译安装 php 时未指定
--with-config-file-path—— 后期安装 redis 等扩展后一直未生效,查看phpinfo()输出信息Configuration File (php.ini) Path和Loaded Configuration File选项是否和手动复制的 php.ini 路径一致,不一致则改为一致。[warn] nginx 客户端请求体被写入临时文件
1
[warn] 6332#0: *9 a client request body is buffered to a temporary file /usr/local/nginx/client_body_temp/0000000001
处理方法:
client_body_buffer_size 1024k;加大到 1024K,默认 16K 太小
七、其他
- 各种 O(管理层职位缩写) —— 原文
| 缩写 | 英文全称 | 中文 | 职责 |
|---|---|---|---|
| CEO | Chief Executive Officer | 首席执行官 | 企业中负责日常经营管理的最高级管理人员 |
| CFO | Chief Financial Officer | 首席财务官 | 财务总监,掌握企业的财务信息和现金资源 |
| COO | Chief Operating Officer | 首席运营官 | 负责监督管理每日活动的高阶官员,监测每日的公司运作 |
| CIO | Chief Information Officer | 首席信息官 | 最高决策层成员,负责制定公司信息政策、标准、程序,管理并控制全公司信息资源 |
| CTO | Chief Technology Officer | 首席技术官 | 企业内负责技术的最高负责人,一般为 IT 精英,有时与 CIO 是同一人 |
| CKO | Chief Knowledge Officer | 知识长 | 掌管企业内所有知识管理相关的工作 |
| CPO | Chief Procurement Officer | 首席采购官 | 主持采购部全面工作,直接向首席执行官汇报 |
| CGO | Chief Game Officer | 首席游戏官 | 现多指锐起公司专为网吧推出的管理系统,非企业高层职位 |
| CMO | Chief Marketing Officer | 市场总监 | 负责市场运营工作的高级管理人员 |
| CSO | Chief Solution Officer | 首席问题官 | 负责挖掘问题、协调缓解问题和解决问题的高级管理人员 |
编程几人
- 蔡德明
- 惠新宸
- 廖雪峰
- 尤雨溪
- 阮一峰
知识形成体系
- 设计模式和算法
- 面向对象和接口
- 计算机网络
- 数据库
- Linux 命令
- 操作系统
- 主流架构
HTTP / 网络客户端库对比
| 库 | 语言/生态 | 同步/异步 | 特点 | 典型场景 |
|---|---|---|---|---|
| httpclient | Java | 同步(旧版) | Apache 老牌 HTTP 客户端,已停止维护,被 HttpComponents HttpClient 取代 | 遗留系统 |
| feign | Java | 同步(可配) | 声明式 HTTP 客户端,写接口 + 注解即可调用,天然整合 Spring Cloud 与负载均衡 | 微服务间 REST 调用 |
| okhttp | Java / Android | 支持异步 | Square 出品,连接池、拦截器、HTTP/2、缓存一应俱全 | Android 与 JVM 应用 |
- GPU/TPU —— 原文
| 对比项 | CPU | GPU | TPU |
|---|---|---|---|
| 全称 | Central Processing Unit | Graphics Processing Unit | Tensor Processing Unit |
| 设计取向 | 通用串行,强单核性能 | 大规模并行,强吞吐 | 专为张量运算定制 |
| 核心数 | 几核 ~ 几十核 | 数千个流处理器 | 数千个乘加单元(MXU) |
| 擅长 | 逻辑控制、分支、复杂调度 | 矩阵/向量并行计算、图像渲染 | 神经网络训练与推理 |
| 精度灵活性 | 高 | 中 | 低(主打 bf16/int8) |
| 生态 | 最成熟 | CUDA 生态成熟 | 依赖 Google 生态(JAX/TF) |
| 典型场景 | 通用计算、服务端 | 深度学习训练、图形渲染 | 大规模推理、Google 云上训练 |
区块链 —— 原文
- 本质:区块链是一个去中心化的分布式账本,由一串按时间顺序链接的区块组成,每个区块保存一批交易记录。
- 四大核心技术:① 哈希链(每个区块存前一个区块的哈希,改动任一区块会导致后续全部失效);② 非对称加密与数字签名(证明交易由私钥持有者发起);③ 分布式共识(PoW 工作量证明 / PoS 权益证明,解决”谁来记账”);④ P2P 网络(节点互相同步,无中心服务器)。
- 关键特性:不可篡改、可追溯、去中心化、公开透明(公有链)。
- 不可能三角:去中心化、安全性、可扩展性三者难以同时最优,这也是各类公链方案权衡的核心。
- 局限:吞吐量低(比特币约 7 TPS)、确认延迟高、能耗大(PoW)、智能合约漏洞风险、私钥丢失即资产丢失。
Activiti 与 BPMN2.0 规范 —— 原文
- BPMN 2.0(Business Process Model and Notation)是 OMG 组织制定的业务流程建模与标记法标准,用图形化的方式描述业务流程,同时定义了标准的 XML 交换格式,使不同工具之间可以互通。
- Activiti 是一个轻量级的 Java 工作流引擎,遵循 BPMN 2.0 规范,把画好的流程图(
.bpmn)部署到引擎中,由引擎驱动流程流转、分配任务、记录流程实例状态。 - 核心概念:
| 概念 | 说明 |
|---|---|
| ProcessDefinition | 流程定义,一次部署的流程图模板 |
| ProcessInstance | 流程实例,按定义跑起来的一次具体流程 |
| Task | 任务,需要人(UserTask)或系统(ServiceTask)处理 |
| Gateway | 网关,决定流程分叉与合并(排他/并行/包容) |
| Event | 事件,开始、结束、边界、中间捕获/抛出事件 |
- 如何做好需求分析和设计? —— 原文
- 需求分析四步:① 明确业务目标(这个需求解决什么问题、怎么衡量成功);② 识别角色与场景(谁用、在什么情况下用、完整流程是什么);③ 梳理功能与非功能需求(性能、并发、安全、兼容性);④ 确认边界与优先级(哪些不做、哪些先做)。
- 设计阶段的关注点:领域模型(表结构、实体关系)→ 接口设计(API 契约、入参出参、错误码)→ 流程与状态机(关键业务的状态流转)→ 异常与边界(失败重试、幂等、回滚)→ 监控与灰度(上线后怎么看效果、怎么回退)。
- 质量判断标准:需求文档让测试能直接写用例、接口文档让前端能直接联调,说明分析到位了;否则就是还有歧义没消除。