/images/avatar.png

我的工具集

只写一些每天都能用上的或者无替代的工具。 生产: 印象笔记+剪辑插件:知识库构建+书影音笔记归档 typore:最好的markdown编辑器用于日常工作文档产出 onedriver:文档同步以及版本管理 滴答清单:日历视图作为时间-事件日志、纪念日管理、检查清单、想要的东西目标、日常待做事务 flomo:闪念,想到什么就写什么,关键是记下来,部分替代微信文件传输助手。隔段时间归档部分。 snipaste:随意的截图、顶置显示、批注 xshell+xftp:终端+方便的服务器文件传输 vscode:开源项目代码阅读,C++跳转新版本都有了,不折腾。 网易邮箱大师:简单的邮件管理 centbrowser:全局手势是痛点 utool:快速打开、文件搜索 powertoys:方便的分屏,快速把窗口布置到屏幕的一部分 office:ppt、excel、visio 其他: 分区助手:换硬盘时系统迁移、磁盘分区调整 v2ray:翻墙 office tool:支持基本所有版本的office安装、激活、清理垃圾 2345看图王去广告版:图片、pdf阅读器 feedly+rsshub插件:rss阅读器+rsshub源生成支持把github、知乎专栏等生成rss 油猴插件:百度、微博、贴吧页面精简去除、豆瓣页面增强、返利推广连接清洗 沙拉查词:使用彩云小译,表现优于google翻译 豆瓣:书影音列表、短评 微信阅读:常见的出版书、大部分网络小说阅读工具

设计模式的个人总结

创建型模式 工厂方法 简单来说就是提供一个create方法 代码两个变化方向,一个是子类的扩展,一个是框架层的不变。 另外还有一种用法和单例有点像,提供一个create接口,但是返回的可能是公用的对象。 抽象工厂 单个类里有很好个create方法,用于创建不同的产品。 一般把创建操作独立成一个类A,然后组合进另一个类B。类B利用类A的接口完成具体的业务。 生成器 和抽象工厂有点像的,只是这里更强调步骤。生成器是把步骤隐藏,抽象工厂的步骤是不变的。 两个变化的方向,一个是创建不同的产品、一个是构建步骤不同,导致有两个继承树。 原型 就是一个clone接口,能够从已有的类copy一个新的出来。 比较适合的场景 怪物、AI的创建,怪物种类太多了,那么直接按照怪物的行为划分更下层的子类,通过组合的形式构造出来成千上万种怪物。 深入设计模式这种还要搞一个prototype继承树有点二,在游戏里组合用的更多些。 单例 全局访问点、通过封装保证只会创建出一个、延迟初始化 用的太多了,不过要写出一个线程安全的单例其实不容易。 隐式的构造时机,可能导致隐藏bug,不适合服务器场景,服务器要求行为固定 全局只能有一个对象,好处是调用可以少穿一个参数,坏处就是这个全局只有一个对象的限制很蛋痛,没法扩展成多个。 结构型模式 适配器 简单说就是套个壳,伪装成另外一种东西。非常朴素的一种设计模式,很常用。 装饰模式和适配器不太一样,装饰主要是想偷偷做一点其他事情。 桥接 功能和名字匹配,两种不同类型对象的中间连接的部分。 对象可以独立扩展,桥接部分也能独立扩展,这里面有三个变化的方向。 组合 同一类对象组合成一个大对象,偶尔用。 组合的模式可以有多种:并列、树等等。 使用范围有限,大部分类这样组合起来语义上就不通了。 装饰 简单来说就是穿一层衣服,增强功能。 外观 相当于一个大的模块,提供一个api类,把对外暴露的接口都放在这个类里。 使用者就不用关心模块内部的实现,最简单做法就是搞一个api.hpp暴露一些全局函数。 一个模块可以提供好几个外观。 享元 省内存,最常见的就是文字处理程序依靠该模式处理字符串。 游戏行业有很多特效、物件都可以用这个方法处理。 代理 非常常用的模式,比如数据库代理、RPC stub。 代理模式提供相同的接口,但是真实对象在另外的地方。 行为模式 责任链 常见于消息处理,一个消息过来,被一个链条下的handle消费。 有两种做法,一种是调用下一个节点由框架来做,一种是由节点来做。 节点来做比较适合插入时间统计的代码,这个节点相当于下一个节点的装饰器。然后也可以根据业务看是否取消继续调用,适合做拦截器。 形式可以不是链状,树也行,随意啥形状都行。 命令 游戏行业用的比较多的就是对同一个玩家输入的操作执行不同的响应。 本质上是框架复用。 迭代器:没啥好说的,框架复用,迭代模式任意扩展,stl用的太多了。 中介者 依赖导致,解除类之间互相调用产生的网状结构。 网状结构没了,都依赖中介者,这样只要改中介者,代码更容易改。 备忘录 用的很少的一个模式,就是把状态从对象中剥离,可以任意恢复状态。 观察者: 天天用的玩意,解耦,依赖倒置。 通知没有顺序,调用关系隐蔽,重入风险。 状态:和命令模式类似,是为了对同一个行为产生不同的反应,但是状态模式操作是一组的。 策略 代码分成两部分,上下文和策略,策略能独立扩展,上下文不变。 和命令模式有点像,不过目的不一样,命令不强调这个上下文。 模板方法:框架复用,和模板差不多,替换几个预设的步骤。 访问者: 双分发,不是很好用的一个模式,子类扩展还要改visitor。 框架复用,visitor就是一个遍历,然后每种类型对象调用不通的接口,接口的

一致性与共识算法

本文从《数据密集型引用系统设计》、Paxos lecture (Raft user study)(https://www.youtube.com/watch?v=JEpsBg0AO6o) 各截取了部分。 挑战 故障 数据: 磁盘: 4% 年损坏率 服务器宕机时间: 0.1% 或更长 IDC间丢包率: 5% ~ 30% 下面是几种分布式系统下典型的问题: 当通过网络发送数据包时,数据包可能会丢失或者延迟。同样,回复也可能会丢失或延迟。所以如果没有收到回复,并不能确定消息是否发送成功。 节点的时钟可能会与其他节点存在明显的不同步,时钟还可能会突然向前跳跃或者倒退,依靠精准的时钟存在一些风险,没有特别简单的方法来精确测量时钟的偏差范围。 进程可能在执行过程中的任意时候遭遇长度未知的暂停(一个重要的原因是垃圾回收),结果它被其他节点宣告失效,尽管后来又恢复执行,却对中间的暂停毫无所知。 部分失效可能是分布式系统的关键特征。只要软件试图跨节点做任何失效,就有可能出现失败,或者随机变慢,或者根本无应答(最终超时)。对于分布式环境,我们目标是建立容忍部分失效的软件系统,这样即使某些部件发生失效,系统整体还可以继续运行。 线性化与CAP理论 线性化:表现得好像只有一个数据副本,且其上的所有操作都是原子的。 为什么要线性化? 非线性化系统的问题: 上面违背线性化只产生了一个比较小的问题,仅仅是展示页面不一致。但是如果核心业务违背线性化,可能导致严重问题。常见的就是集群选主,可能会出现两个主,导致脑裂。 常见复制算法,对线性化的支持: 主从复制(部分支持) 只有主写入读取的话,其他都是备份的情况下,是线性化的。但是不能做高高可用。 异步复制、主脑裂、从读等情况,不可线性化。 多主复制(不可线性化) 多副本冲突 无主复制(可能不可线性化) 能够实现高可靠、高可用性、数据完整有保证 会出现脏读、更新丢失等情况 具体看ddia吧,不展开了,用的比较少 共识算法(可线性化) 具体之后讨论。 线性化的代价以及CAP理论: FLP FLP 不可能定理是分布式系统领域最重要的定理之一,它给出了一个非常重要的结论:在网络可靠并且存在节点失效的异步模型系统中,不存在一个可以解决一致性问题的确定性算法。 In this paper, we show the surprising result that no completely asynchronous consensus protocol can tolerate even a single unannounced process death.

高性能libcurl

本文主要介绍一下curl接口的使用方法,以及获取高性能的一些实践。 什么是libcurl?用处? 1 libcurl is a free and easy-to-use client-side URL transfer library, supporting DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet and TFTP. libcurl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, cookies, user+password authentication (Basic, Digest, NTLM, Negotiate, Kerberos), file transfer resume, http proxy tunneling and more! 官网摘的一段,意思大概是免费且容易使用的url传输库,支持下面一堆特性。

简易function

本文主要讲一下怎么实现一个简易版本的function<>模板,从c++ templates第二版摘出。 出发点 一个简单的例子,下面这个模板上述能够接受任意可调用的对象,lambda表达式、函数指针、仿函数。 1 2 3 4 5 6 7 template<typename F> void for_int_up(int n, F f) { for (int i = 0; i <= n; ++i) { f(i); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void print_int(int i) { std::count << i << ' '; } int main() { int sum = 0; for_int_up(5, [&sum](int i) { sum += i; }); for_int_up(5, print_int); return 0; } 像for_int_up这样的函数其实有两个问题:

读书摘录-存在主义心理治疗

本书涉及四个终极关怀:死亡、自由、孤独和无意义。个体与这些生命真相的正面交锋,构成了存在主义动力性冲突的内容。 死亡。最显而易见的、最容易理解的终极关怀就是死亡。我们现在存在,但是总有一天,这种存在会终止。死亡将如期而至,没有逃脱之路。这是一个恐怖的真相,能引发我们巨大的恐惧。用斯宾诺莎的话来说,“每一事物都在尽力维持自身的存在”;而存在的一个核心冲突就是,对死亡必然性的意识与继续生存下去的愿望之间的张力。 自由。另一个相对来说不太容易理解的终极关怀是自由。一般来说我们都认为自由是一个毋庸置疑的积极概念。有史以来,人类不是一直在渴望并为自由而奋斗吗?然而从终极层面来看,自由是与忧惧偶联在一起的。在存在的意义上,“自由”意味着外部结构的空白。与日常经验相反的是,人类并不是进入(和离开)一个拥有内在设计、高度结构化的宇宙。实际上,个体对他自己的世界、生活设计、选择以及行为负有全部责任——也就是说,个体是自己世界的创造者。“自由”在这种含义上,带有一种可怕的暗示:它意味着在我们所站立的地方并不坚实一什么都没有,是空的,无底深渊。所以,存在主义一个关键的动力性冲突就是,们无根基的处境与我们对根基与结构的渴望之间的冲突。 存在性孤独。第三个终极关怀是孤独不是伴随着寂寞的人际性孤独,也不是个人内心的孤独(与自身的其他部分隔离),而是一种根本性孤独既与生命隔绝,也与世界隔绝—隔绝在所有其他孤独之下。无论我们之间变得有多么亲密无间,仍然存在一个最终无法逾越的鸿沟;我们每个人都是独自一人进入这种存在,同时也注定要独自离开。一方面是我们对自身绝对孤独的意识,另一方面是对接触、保护的渴望,以及成为一个更大整体的一部分的愿望在性冲突就是这两个方面之间的张力。 无意义。第四个终极关怀或存在的既定事实是无意义。如果我们注定得死,如果我们构建我们自己的世界,如果每一个人最终都是独自一人身处于一个无关紧要的世界之中,那么生命有什么意义我们为什么要活着?我们应该怎样活着?如果并不存在为我们预先设计的蓝图,那么我们每个人就必须构建自己的生命意义。然而,个人自己创造出来的意义能否坚强到令其能容忍生活?人类这种寻找意义的生物,却被投入到本身毫无意义的宇宙之中,于是,存在的动力性冲突便从进退维谷的境地中滋生出来。