推荐几本 Java 并发编程的书

最近,D瓜哥的一个小伙伴向我抱怨,Java 并发是个大坑,问我怎么看?我回答,当然是用眼睛看啊… D瓜哥觉得,想学好 Java 并发,最重要的还是啃书。幸运的是,Java 中还是有不少关于并发的优秀书籍可以看。正好利用这个机会,把看过的、个人认为还不错的书推荐一波。没有看过的就不多言了。 Java并发编程实战 如果只选一本书来深入研究并发,那肯定是这本书。 Java并发编程实战 (豆瓣) — 这本书是必看的。JDK 中 JUC 就是这本书的作者们写的。虽然书名含有 Java 一次,但是,里面更多是原理性的东西,各种语言都适用。只是例子少了一些。这本书需要多读几遍。(据说翻译不行,推荐看英文版) 放个英文版图片镇楼: Java并发编程的艺术 Java并发编程的艺术 (豆瓣) — 这本书也不错,讲了很多源码方面的内容,非常棒。另外,在讲解 Double Lock 方面的知识时,涉及了很多 Java Memory Model 方面的知识,可以先看看 深入理解Java虚拟机(第3版)(豆瓣) 最后两章的内容,来提前补充一下这么方面的知识。 实战Java高并发程序设计 实战Java高并发程序设计(第2版) (豆瓣) — 这本书也不错,针对 Java 8 写的,Java 8 中的很多新知识都有涉猎,例子也很全面。广度和深度,得到了兼顾,非常棒。 Java编程思想 Java编程思想(第4版)(豆瓣) — 虽然这本书已经出来十余年了,但是依然经典。第 21 章 并发,用大量的例子和陈述来介绍并发。非常棒。美中不足,是针对 Java 5 编写的,现在已经 Java 8 了。不过,作者又出了一本书,可以理解成升级版。

分布式事务概述

现在手机银行转账已经司空见惯。但是,D瓜哥一直在思考,银卡跨行转账是如何保证事务一致性的?借机就对分布式事务,做了简单地了解。 2PC 两阶段提交(2pc, two-phase commit protocol),2pc是非常经典的强一致性、中心化的原子提交协议。中心化是指协议中有两类节点:一个中心化协调者节点(coordinator)和N个参与者节点(participant、cohort)。 顾名思义,两阶段提交协议的每一次事务提交分为两个阶段: 在第一阶段,协调者询问所有的参与者是否可以提交事务(请参与者投票),所有参与者向协调者投票。 在第二阶段,协调者根据所有参与者的投票结果做出是否事务可以全局提交的决定,并通知所有的参与者执行该决定。在一个两阶段提交流程中,参与者不能改变自己的投票结果。两阶段提交协议的可以全局提交的前提是所有的参与者都同意提交事务,只要有一个参与者投票选择放弃(abort)事务,则事务必须被放弃。 两阶段提交协议也依赖与日志,只要存储介质不出问题,两阶段协议就能最终达到一致的状态(成功或者回滚) 优点 强一致性,只要节点或者网络最终恢复正常,协议就能保证顺利结束;部分关系型数据库(Oracle)、框架直接支持 缺点 网络抖动导致的数据不一致: 第二阶段中协调者向参与者发送commit命令之后,一旦此时发生网络抖动,导致一部分参与者接收到了commit请求并执行,可其他未接到commit请求的参与者无法执行事务提交。进而导致整个分布式系统出现了数据不一致。 超时导致的同步阻塞问题: 2PC中的所有的参与者节点都为事务阻塞型,当某一个参与者节点出现通信超时,其余参与者都会被动阻塞占用资源不能释放。 单点故障的风险: 由于严重的依赖协调者,一旦协调者发生故障,而此时参与者还都处于锁定资源的状态,无法完成事务commit操作。虽然协调者出现故障后,会重新选举一个协调者,可无法解决因前一个协调者宕机导致的参与者处于阻塞状态的问题。 基于两阶段提交的分布式事务在提交事务时需要在多个节点之间进行协调,最大限度地推后了提交事务的时间点,客观上延长了事务的执行时间,这会导致事务在访问共享资源时发生冲突和死锁的概率增高,随着数据库节点的增多,这种趋势会越来越严重,从而成为系统在数据库层面上水平伸缩的"枷锁", 这是很多Sharding系统不采用分布式事务的主要原因。 3PC 三阶段提交协议(3pc Three-phase_commit_protocol)主要是为了解决两阶段提交协议的阻塞问题,从原来的两个阶段扩展为三个阶段,并且增加了超时机制。 3PC 的三个阶段分别是 CanCommit、PreCommit、DoCommit CanCommit 协调者向所有参与者发送CanCommit命令,询问是否可以执行事务提交操作。如果全部响应YES则进入下一个阶段。 PreCommit 协调者向所有参与者发送PreCommit命令,询问是否可以进行事务的预提交操作,参与者接收到PreCommit请求后,如参与者成功的执行了事务操作,则返回Yes响应,进入最终commit阶段。一旦参与者中有向协调者发送了No响应,或因网络造成超时,协调者没有接到参与者的响应,协调者向所有参与者发送abort请求,参与者接受abort命令执行事务的中断。 DoCommit 在前两个阶段中所有参与者的响应反馈均是YES后,协调者向参与者发送DoCommit命令正式提交事务,如协调者没有接收到参与者发送的ACK响应,会向所有参与者发送abort请求命令,执行事务的中断。

Google 三驾马车:MapReduce、GFS、Bigtable

MapReduce MapReduce编程模型来自函数式编程,包含两个最基本的算子:map,reduce 将一个运算任务分解成大量独立正交的子任务,每个子任务通过map算子计算,得到中间结果,然后用reduce算子进行聚合,得到最终结果。 这两个算子有一个很重要的特征:确定性的纯过程调用(pure function),函数既不会修改输入,也不存在中间状态,也没有共享的内存。因此,输入一致的情况下,输出也是一致的,这大大方便了容错性设计。 系统中有两类主要的进程节点:master(单点),worker(多个)。其中,worker根据不同的计算任务,又分为map worker(对应上图中的Map phase)、reduce worker(对应上图中的Reduce phase)。 master是系统的中心节点,负责计算任务到worker节点的分配,同时监控worker节点的状态。如果某个worker计算太慢,或者宕机,master会将该worker进程负责的计算任务转移到其他进程。 map worker从GFS(google file system)中读取输入数据,然后将中间结果写到本地文件;reduce worker从master处得知中间结果的问题,通过rpc读取中间文件,计算之后将最终结果写入到可靠存储GFS。生产环境中,一个MapReduce过程的输出通常是另一个MapReduce计算的输入,类似Unix 的 pipeline,只不过unix pipeline通过stdin、stdout连接两个程序,而MapReduce使用GFS连接两个计算过程。 Scalability 由于计算任务的正交性,很容易通过增加map worker、reduce worker来处理计算任务的增长。Input file 到 Map phase这个阶段,使用了基于范围(range based)的分片方法,master作为元数据服务器会记录split到worker的映射关系。 Availability 系统对worker的容错性较好,但对master的容错性较差。 对于map worker,计算结果是写到本地文件,本地文件的位置需要通知到master,即使同一个task被多个map worker执行,单点的master只会采纳一份中间结果。而且上面提到了map function是pure function,所以计算结果也是一样的。 对于reduce worker,reduce task的计算结果会先写到临时文件(temporary file),task完成之后再重命名写入gfs,那么如果一个reduce task再多个reduce worker上计算,那么会不会有问题呢,答案是不会的 Performance data locality — 将任务调度到数据所在的节点进行计算,减少网络传输; backup task — master在发现某个worker上的task进展异常缓慢的时候,会将这个task调度到其他worker,以缩短这个任务(Job)的完成时间。 GFS GFS(Google File System)是Google研发的可伸缩、高可用、高可靠的分布式文件系统,提供了类似POSIX的API,按层级目录来组织文件。

HTTP 123

HTTP1.0 根据谷歌的调查, 现在请求一个网页,平均涉及到 80 个资源,30 多个域名。考虑最原始的情况,每请求一个资源都需要建立一次 TCP 请求,显然不可接受。HTTP 协议规定了一个字段 Connection,不过默认的值是 close,也就是不开启。 HTTP1.1 Pipeline 是为了减少不必要的 TCP 连接,但依然存在队头阻塞(HOC)的缺点,一种解决思路是利用并发连接减少某一个 HOC 的影响,另一个是共享(注意与复用的区别) TCP 连接,直接避免 HOC 问题的发生。 HTTP1.1 的缺陷 高延迟 — 队头阻塞(Head-Of-Line Blocking) 当有多个串行请求执行时,如果第一个请求不执行完,后续的请求也无法执行。 支持并发请求是解决解决 HOC 问题的一种方案,并发请求并非是直接解决了 HOC 的问题,而是尽可能减少 HOC 造成的影响。 将同一页面的资源分散到不同域名下,提升连接上限。 减少请求数量 内联一些资源:css、base64 图片等 合并小文件减少资源数 无状态特性 — 阻碍交互 明文传输 — 不安全性 HTTP 1.

暗想

理智告诉我该走了, 但情感却恋恋不舍; 大脑告诉我放手吧, 但心依旧在沦陷; 认识你让生活诗情画意, 想起你忍不住嘴角上扬, 思念你梦都是甜的。 想做你的指南针, 带你周游世界; 带你翱翔太空; 带你去梦想的远方。 想做你的眼镜, 带你观历史的沧海桑田; 带你赏自然的鬼斧神工; 带你看艺术的侠骨柔情。 想做你的厨师, 可口的早餐等你醒来; 丰盛的晚餐等你回家。 好想用心爱你一次, 爱你就像爱生命; 我挣钱养家,你貌美如花; 我用坚强的臂膀, 构建温馨的家。 即使外面狂风暴雨, 家中依然四季如春。 好想和你站在一起, 勇往直前,彼此成就。 你做园丁, 浇灌祖国的花朵; 我做篝火, 温暖家庭,照亮社会。 想说的话,千言万语, 却不能说出口。 想见的人,魂牵梦绕, 却咫尺天涯。 远远祝福你, 事事顺心,桃李天下。 我渴望爱的垂涎, 但不要怜悯的爱。 我将继续加油, 做生活的愚公, 逢山开路,遇水搭桥。 Note 遥知不是雪,为有暗香来。 知音难觅,弦断有谁听?

《解读基金》之读书笔记

这个月断断续续把季凯帆的 《解读基金——我的投资观与实践(修订版)》读完了,秉持读完一本,消化一本的读书理念,做一下读书笔记,整理消化一下书中的内容。 目前房地产不景气,银行利息跑不赢 CPI 的情况下,证券市场是不错的可选性。首先,有政府在背后支撑、监督,不会像 P2P 那样随时暴雷跑路;其次,多方资料显示,长期来看,美国指数基金的收益率在 10% 左右,妥妥跑赢 CPI。第三,流动性好,随手都可以出手(当然有可能会亏损),最长一周时间就可以到账。(节假日除外)第四,起始资金低,几乎没有限制(支付宝买基金十元起步),相比买房动辄几十万,这几乎可以认为没有门槛。实际上,关键的问题是如何投资证券市场。 学习借鉴别人的成功经验是迅速提高自己能力的最佳办法之一。阅读这本书,也是学习别人的成功经验,提高自己的投资能力。 D瓜哥在 “《如何阅读一本书?》之读书笔记” 中介绍了一种读书方法,这次也按照这个读书方法把书的内容梳理一遍。 四个基本问题 一个阅读者要提出的四个基本问题: 整体来说,这本书到底在谈些什么?你一定要想办法找出这本书的主题,作者如何依次发展这个主题,如何逐步从核心主题分解出从属的关键议题来。 作者细部说了什么,怎么说的?你一定要想办法找出主要的想法、声明与论点。这些组合成作者想要传达的特殊讯息。 这本书说得有道理吗?是全部有道理,还是部分有道理? 这本书跟你有什么关系? 问题 针对这本书,D瓜哥有如下一下问题: 股市都有哪些风险? 常说的系统性风险都具体指哪些? 配置什么样的投资产品?什么比例比较合适? 基金是怎么运作的?怎么收费的? 如何选择基金?需要关注哪些方面? 何时卖出基金? 场内 ETF 指数基金和场外 ETF 增强基金有啥区别? 我的操作中,有什么不合理的地方? 投资准备 总结 投资,说穿了就是让钱生钱。让钱生钱,这其实是所有富人的生财之道。-- D瓜哥觉得把“富人”换成“投资人”更合适。

动态规划入门

Tip 本篇文章是 D瓜哥 读《算法导论》的读书笔记。记录下来是为了方便整理思路,以便啃下“动态规划”这块骨头。 目前侧重记录书中关于“动态规划原理”的介绍。接下来会把书中的例子结合 Java 代码演绎一遍。后续会根据D瓜哥的学习和理解,逐步完善。最终希望达到通过这一篇文章,就能学会、理解动态规划。 山高水远,道阻且长,愿一起努力!  — 2020年01月23日 动态规划(dynamic programming)与分治方法相似,都是通过组合子问题的解来求解原问题(在这里,“programming”指的是一种表格法,并非编写计算机程序)。 分治方法将问题划分为互不相交的子问题,递归地求解子问题,再将它们的解组合起来,求出原问题的解。 动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题(子问题的求解是递归进行的,将其划分为更小的子子问题)。 在这种情况下,分治算法会做许多不必要的工作,它会反复地求解那些公共子问题。 动态规划算法对每个子子问题只求解一次,将其解保存在一个表格中,从而无需每次求解一个子子问题时都重新计算,避免了不必要的计算工作。 动态规划方法通常用来求解最优化问题(optimization problem)。 设计一个动态规划算法的步骤: 刻画一个最优解的结构特征。 递归地定义最优解的值。 计算最优解的值,通常采用自底向上的方法。 利用计算出的信息构造一个最优解。 算法原理 适合应用动态规划方法求解的最优化问题应该具备的两个要素:最优子结构和子问题重叠。 最优子结构 用动态规划方法求解最优化问题的第一步就是刻画最优解的结构。如果一个问题的最优解包含其子问题的最优解,则称此问题具有最优子结构性质。因此,某个问题是否适合应用动态规划算法,它是否具有最优子结构性质是一个好线索。 发掘最优子结构性质的通过模式 证明问题最优解的第一个组成部分是做出一个选择。做出这次选择会产生一个或多个待解的子问题。 对于一个给定问题,在其可能的第一步选择中,你假定已经知道哪种选择才会得到最优解。你现在并不关心这种选择具体是如何得到的,只是假定已经知道了这种选择。 给定可获得最优解的选择后,你确定这次选择会产生哪些子问题,以及如何最好地刻画子问题空间。 利用“剪切-粘贴”(cut-and-paste)技术证明:作为构造原问题最优解的组成部分,每个子问题的解就是它本身的最优解。证明这一点是利用反证法:假定子问题的解不是其自身的最优解,那么我们就可以从原问题的解中“剪切”掉这些非最优解,将最优解“粘贴”进去,从而得到原问题一个更优的解,这与最初的解是原问题最优解的前提假设锚段。

《如何阅读一本书?》之读书笔记

D瓜哥在 “告别 2019,迎接 2020” 中已经提过,今年的一个重要改进就是把书读透,学以致用,不求速度但求质量。并且,还提到要重读《如何阅读一本书》和《如何有效阅读一本书》,以求提高读书技能,把书读透。 最近在读《如何阅读一本书》,大概读了五分之一。最近有个想法,何不用《如何阅读一本书》中介绍的方法来阅读《如何阅读一本书》呢?熟悉编程(尤其是 Ruby)的朋友估计该会心一笑,有点元编程的感觉。 D瓜哥这里先大概介绍一下书中的内容,然后再根据读书方法来剖析这本书。 作者在全书第一章就开宗明义地写道:这本书为那些想把读书的主要目的当作是增进理解能力的人而写。 我们的目标就是:第一提醒读者,阅读可以是一件多少主动的事。第二要指出的是,阅读越主动,效果越好。 阅读艺术是一个凭借着头脑运作,除了玩味读物中的一些字句之外,不假任何外助,以一己之力来提升自我的过程。 蒙田说:“初学者的无知在于未学,而学者的无知在于学后。” 阅读的艺术包括了所有非辅助型自我发现学习的技巧:敏锐的观察、灵敏可靠的记忆、想象的空间,再者当然就是训练有素的分析、省思能力。 要避免这样的错误 —— 以为读得多就是读得好的错误。 做一个自我要求的读者 主动阅读的核心就是:你在阅读时要提出问题来 — 在阅读的过程中,你自己必须尝试去回答的问题。 四个基本问题 一个阅读者要提出的四个基本问题: 整体来说,这本书到底在谈些什么?你一定要想办法找出这本书的主题,作者如何依次发展这个主题,如何逐步从核心主题分解出从属的关键议题来。 作者细部说了什么,怎么说的?你一定要想办法找出主要的想法、声明与论点。这些组合成作者想要传达的特殊讯息。 这本书说得有道理吗?是全部有道理,还是部分有道理? 这本书跟你有什么关系? 做笔记的方法 画底线 —— 在主要的重点,或重要又有力量的句子下画线。 在画底线处的栏外再加画一道线。 在空白处做星号或其他符号 —— 要慎用。 在空白处编号 —— 作者的某个论点发展出一连串的重要陈述时,可以做顺序编号。 在空白处记下其他的页码 —— 强调作者在书中其他部分也有过同样的论点,或相关的要点,或是与此处观点不同的地方。

告别 2019,迎接 2020

我的 2019 在 2018 年底,我写了 “2019 年度计划” 对 2019 年做了一个简单的规划。2019 年如白驹过隙,稍纵即逝。又到一年年底,现在对这一年做一个总结。 虽然这一年,我一直在意有这么一个计划,但是从来没有认真总结反思过。为了回顾一下,刚刚又打开计划去看,生活才发现过得如此苍白无力。抛开计划,按时间顺序,从头到尾,随意来说吧。 读书 今年读了几本书: 《小岛经济学》 《小王子(英文版)》 《未来世界的幸存者》 《白夜行》 《教父》 《远见》 《如何阅读一本书?》 《文明之光(第一册)》 《基督山伯爵》 《Kubernetes in Action》 《富爸爸穷爸爸》 《巴菲特与索罗斯的投资习惯》 《幸福的方法》 《魔鬼聊天术》 《拆掉思维里的墙》 挑选几本来简单说说吧。 《小岛经济学》 《小岛经济学》是今年读完的第一本书,也算是去年留下的一个尾巴。奥地利经济学派主张政府不干预的观点。这本书简单描述了经济发展的过程,从莽荒时代,手工作业开始,逐步引入工具,提高生产力;随着生产力的提升,人口的增多,经济活动增多,开始物物交换;从物物交换过渡到货币交易,然后银行业兴起;生产力再次提高,以及货币的增加,投资也成为必要,资本市场应运而生;随着地区优势的凸显,资源整合也势在必行,接着发展起了跨国贸易,换汇成为必要,汇率也就被引入进来;随着资本市场的繁荣,埋藏的地雷被引爆,通货膨胀,货币贬值,资本市场崩溃,社会进入大萧条,然后重置继续发展……

OKR 学习笔记 - 未来展望

29 | 他们落地 OKR 都失败了,原因出在哪儿? 为何这家初创公司落地 OKR 失败了? 拿 OKR 当 KPI 用,只是通过 OKR 看结果,而忽略了 OKR 执行过程中的跟踪与复盘,最终导致 OKR 没用对,KPI 也没用好。 对于初创公司而言,生存固然重要,但成长也不可忽视,OKR 既能实现目标,又能关注成长。 为何这家传统企业落地 OKR 失败了? 为何这家互联网公司落地 OKR 失败了? 总结 没有充分理解 OKR 的核心概念,更没有真正体会到 OKR 的精髓,容易将 OKR 当 KPI 用。 当正确理解 OKR 后,就应该快速落地,并及时跟踪落地效果,持续收集员工反馈。 OKR 的本质就是简单,所以没必要让 OKR 落地变得复杂,无需与流程和制度相绑定。 30 | 用什么工具,能加强OKR落地效果? OKR 初步落地,用什么工具? 与“表格”相比,我更倾向于“看板”,不是电子看板,而是实体看板,需要将它固定在墙上,而且办公区域内,越多的同事看到它越好。 看板使得 OKR 的价值发挥到了极致。