IT技术博客大学习 共学习 共进步
首页 / 廖雪峰
IT 2018-12-26 23:38:42 / 累计浏览 2,280

交易系统如何确保账簿100%准确

这篇讲的是如何从设计层面根本性解决交易系统的账簿对账难题。作者指出,对账处理不好会带来巨大的人力成本和线上修改风险,因此提出一个核心设计原则:时刻保持整个系统的资产负债表为零。 文章以一个比特币交易系统为例,展示了只存储用户余额(资产)的账户表为何难以对账。关键一步是引入一个虚拟的“负债”(DEBT)账户来平衡整个资产负债。这样,无论用户间如何交易、资产如何转移(包括手续费进入FEE账户),所有账户的余额按币种求和,结果理论上都应精确为零。 基于此,对账逻辑变得极其简单:在每笔交易后执行一句SQL查询,检查各币种余额总和是否为零。文章还解释了用户入金和出金的本质是资产与负债账户之间的转移。这套设计不仅让系统能自动化、近乎实时地验证账簿准确性,也极大简化了财务核算,体现了用清晰架构提升系统可靠性的思路。

IT 2016-03-10 23:52:05 / 累计浏览 1,400

彪悍的职业不惧阿尔法狗

这篇文章从阿尔法狗与李世石的对弈讲起,引出了一个更值得深思的现实问题:在机器学习浪潮下,哪些人的职业未来会受到冲击?作者先以戏谑的方式提出了一个关于AI文明发展的宏大猜想,随后将话题拉回地面——Google为机器学习专家开出超200万美元年薪,正是因为资本正在押注这项技术的盈利潜力。 核心观点很明确:机器学习将首先替代那些重复性强、无需创造性思考的岗位。例如,机械搬运网络段子的小编辑,其工作可能很快被推荐算法取代。相反,那些需要灵感与创造性的职业,比如段子手、艺术家、导演,以及最重要的软件工程师,则拥有更长的“安全期”。作者甚至断言,当机器能完全替代程序员时,那可能已是AI文明终结地球之时。 因此,文章最终将“程序员”定义为地球上最后一个消失的职业,并建议有志者不妨从Python开始,踏入这个面向未来的领域。

IT 2015-07-23 13:43:49 / 累计浏览 6,560

如何设计用户登录

这篇讲的是如何设计一个灵活可扩展的用户登录系统。作者从最常见的用户名+密码登录入手,指出当需要集成微博、QQ等第三方登录时,传统做法——在Users表中不断新增列来存储OAuth信息——会导致表结构日益臃肿,维护成本很高。 核心解决方案是将“用户资料”与“认证信息”进行分离。具体来说,将Users表精简为只存放用户个人资料(Profile);而将登录认证(Authentication)过程独立出来。本地密码登录维护一个LocalAuth表,而微博、QQ等第三方OAuth登录则统一到一个OAuth表中,通过`oauth_name`字段区分不同来源。 这种设计的好处显而易见:添加新的登录方式(如SAML)只需新增记录或表,无需改动用户主表;一个用户可以绑定多种登录方式;同时,由于Users表不再存放口令等敏感数据,系统安全性也得到了提升。

IT 2015-04-26 23:00:33 / 累计浏览 2,560

编写一个简单的JavaScript模板引擎

这篇讲的是如何从头实现一个轻量级的前端模板引擎。作者从实际场景出发,指出像 Swig 这样的全功能模板引擎有时对于前端简单的 HTML 片段生成显得有些笨重,由此引出了自己动手造一个的需求。 实现思路清晰而巧妙:核心在于将模板字符串编译成一个可执行的渲染函数。具体来说,是通过正则表达式(`/\\{\\s*([a-zA-Z\\.\\_0-9()]+)\\s*\\}/m`)匹配出模板中的变量占位符(如 `{ user.company }`),然后动态生成一个函数代码字符串。这个生成的函数在运行时,会将 `model` 数据绑定到 `this` 上,通过类似 `this.user.company` 的方式直接访问数据并拼接成最终的 HTML 片段。 其中最巧妙的一点是利用了 JavaScript 的 `new Function()` 机制,将模板字符串“编译”为真正的函数对象。这不仅让渲染过程高效,也天然支持了对复杂嵌套属性(如 `user.addr.zipcode`)的解析。文章最后给出的完整 `Template` 构造函数代码,完整地演示了从正则匹配、代码生成到函数编译的全流程,让读者能清晰地理解一个模板引擎最底层的工作原理。

IT 2015-01-23 23:54:56 / 累计浏览 6,280

如何编写一个JSON解析器

这篇讲的是如何从头实现一个JSON解析器。作者从JSON解析器的基本定义出发——即将JSON字符串转换为语言内存中的数据结构,对比了它与XML的差异,并梳理了JSON基本类型与Java数据结构(如Map、List)的映射关系。 文章的核心在于拆解实现思路。它强调解析器应采用流式单次扫描,本质是一个状态机。实现的关键步骤被清晰地勾勒出来:首先,需要封装一个`CharReader`来支持`peek()`操作,以便在不移动指针的情况下预判字符;其次,将原始字符流进一步抽象为Token流(如`BEGIN_OBJECT`、`STRING`等),从而大幅简化状态判断逻辑。最后,文章点出了处理嵌套结构的技巧:利用栈来管理Object和Array的构建,遇到开始标记时创建对应的Map或List并压栈,以此高效地完成递归解析。 整个实现过程体现了从具体到抽象、逐步化繁为简的设计思想,将看似复杂的解析任务分解为字符读取、Token识别和栈操作几个清晰的模块。

IT 2015-01-23 23:52:15 / 累计浏览 3,580

给Nginx配置一个自签名的SSL证书

这篇讲的是如何为Nginx配置一个自签名SSL证书,来快速启用HTTPS安全连接。 在Web开发中,HTTPS几乎是保障浏览器与服务器通信安全的必选方案,但向证书颁发机构申请正式证书往往需要每年几十到几百美元的费用。如果只是为了内部管理或测试目的,自签名证书就能提供一个零成本的解决思路。 文章从SSL证书验证的两种模式切入,解释了为什么普通网站通常只验证服务器证书,并点明自签名证书的适用场景。核心方案部分,作者详细演示了利用openssl创建证书的四步流程:生成密钥、创建签名请求、移除口令并最终签名。为了简化操作,文章还提供了一个shell脚本,以域名www.test.com为例,展示了从运行脚本到输入口令的完整交互过程,以及生成的四个关键文件。 配置环节,文章明确指出Nginx需要加载证书和密钥文件的具体路径,并附上了示例配置。最后还提到一个实用技巧:让Nginx统一处理HTTPS,后端应用服务器只用HTTP连接,这样既发挥了Nginx在处理SSL方面的优势,也避免了其他服务器配置证书的复杂性。整个过程下来,即使是自签名证书,也能让管理员通过浏览器安全地连接到服务器进行维护。

IT 2015-01-23 23:50:52 / 累计浏览 3,000

如何正确地处理时间

这篇讲的是程序开发中一个极易被忽视却至关重要的陷阱:如何正确地存储和处理时间。作者从大多数开发者习以为常的“获取本地时间直接存库”这一操作切入,一针见血地指出了问题的核心——本地时间丢失了时区信息,一旦环境变更,时间数据就会错乱。 文章深入浅出地解释了时区的本质,并引出了“绝对时间”(即时间戳)的概念。作者强调,正确的做法是遵循“存储与显示分离”的原则:在数据库中只存储一个与时区无关的整数或浮点数时间戳。这样,无论服务器时区如何设置,存储的时间值都是全局一致的。显示时,再根据用户的时区将时间戳格式化为字符串。 这种方案带来的好处是根本性的:时间比较和筛选变成了简单的数值运算,彻底摆脱了时区转换的泥潭。文章通过Java示例清晰地展示了一个时间戳如何被正确格式化为不同时区下的本地时间,直观地证明了其有效性。对于任何需要处理国际化时间数据的开发者来说,这篇文章揭示的原理和提供的方案,都是避免未来无尽调试的必备知识。

IT 2015-01-23 23:49:54 / 累计浏览 4,260

如何在一个页面上让多个jQuery版本共存

这篇讲的是在现有网页中如何同时使用多个jQuery版本。文章从实际开发中的痛点出发:老项目可能依赖jQuery 1.5及一堆旧插件,但新功能又想用jQuery 1.11的特性,直接升级会导致旧插件失效。 作者介绍的基础方案是利用jQuery的`noConflict()`方法。通过在新版本导入后调用`var $jq = jQuery.noConflict(true);`,就能恢复页面上`$`和`jQuery`全局变量为旧版本,同时通过局部变量`$jq`来使用新版本,从而实现共存。 但作者指出,直接在页面写多行脚本容易出错(比如被误删或顺序颠倒)。因此,他提出了一个更健壮的封装方案:把自己的新脚本(比如`myscript.js`)写成一个匿名函数,并在其中直接嵌入新版jQuery的压缩源码。这样,脚本内部通过`noConflict`获取的新版jQuery会成为一个局部变量`$`,完全不受页面其他jQuery版本影响。最终,页面只需正确引入旧版jQuery和这个封装好的新脚本即可,实现了解耦与自治。 这个方案的巧妙之处在于,它把版本兼容的复杂性完全封装在一个独立的文件里,让主页面保持干净,也避免了其他开发者误操作的风险。

IT 2015-01-23 23:49:11 / 累计浏览 4,340

JavaScript的闭包问题

这篇讲的是 JavaScript 闭包在循环中一个经典的陷阱。作者从一个看似简单的需求出发:在一个 `for` 循环中创建三个函数,分别打印当前的循环索引。但实际执行时,所有函数都打印了同一个值——循环结束后的最终值。 问题的根源在于闭包捕获的是变量的引用,而非创建时的快照。循环变量 `i` 在所有函数中都是同一个变量,因此函数执行时读取的都是循环结束后那个值。即使尝试在循环内用 `var n = i` 复制一份,由于 JavaScript 缺乏块级作用域,`n` 的作用域依然是整个外层函数,最终也会被后续的迭代覆盖。 作者指出,这条“不要在闭包中直接引用循环变量”的原则,适用于所有函数式语言。正确的做法是创建一个新的作用域来捕获当前迭代的值。文章演示了两种经典方案:一是通过一个额外的函数(如 `function(n){...}`)将当前 `i` 作为参数传入;二是更简洁的立即执行函数表达式(IIFE),在循环体内 `(function(n){...})(i)` 就地创建一个新作用域并传递参数。 这本质上是一个作用域与闭包机制如何相互作用的深度理解问题。掌握这个模式,能帮开发者避免在异步回调、事件监听等场景下产生难以排查的 bug。