Java中的幽灵类型
先上结论:幽灵类型(Phantom Type)是一种可以把有些运行时才能检测到的错误,在编译时检测出来的技巧。按照有些老外的观点,就是“Making Wrong Code Look Wrong”。在面向对象的编程语言之中,幽灵类型的实现,往往与状态模式较为接近,但比状态模式提供了更强的纠错功能。在Java 5 以后的版本里,程序员可以使用泛型。通过泛型的类型参数,Java 中也拥有了幽灵类型的能力。 上面的阐述是不是很难看懂?我也觉得拗口,让我们直接进入具体的例子。假设我们要写一个飞机控制程序,操作飞机起飞或者落地。这个程序有一个非常强的业务约束,就是必须保证飞机一开始必须出现在的地上,只有在地上的飞机可以起飞,只有起飞的飞机可以落地,那么我们应该怎样设计我们的程序(主要是类型关系),来保证这个约束必然成立呢? 让我们先来定义一组状态接口: 123456789101112131415161718192021/** * FlightStatus.java * @author liangchuan...
一段改写的超级账本的链码
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174/* * 改编自 IBM 的源码示例。 */package mainimport ( "bytes" "fmt"...
OOM Killer
Linux 内核有个 OOM Killer 的机制,可以在系统内存不足的时候,通过主动杀死一些进程来释放更多的内存空间。 很多时候,我们可以 ping 通一台服务器,但无法 ssh 上去,因为 sshd 被 OOM Killer 杀掉了。ping 能 ping 通,是因为处在内核态协议栈还能工作,发出回送报文。sshd 则因为是用户态进程,直接被干掉了。 关闭再打开 OOM Killer 的方法: 12echo "0" > /proc/sys/vm/oom-killecho "1″ > /proc/sys/vm/oom-kill OOM Killer 决定是否要杀死一个进程,主要看两个指标: /proc/PID/oom_score 的分数 /proc/PID/oom_adj 可以通过以下方法强制内核不得杀死某个进程: 1pgrep -f "/usr/sbin/sshd" | while...
支付业务
支付牌照是金融体系里唯一还在卖的交易拍照。 金融业务分为三大类:银行、保险、证券。 银行业分为表内和表外的业务。支付是银行业的一部分。 是不是计入资产负债表—表内、表外业务。 表外业务是银行的服务业务,毛利高。 支付是表外业务。 互联网三大赚钱业务(变现场景对应支付的三个工具): 游戏(支付工具)。 广告(大数据量级几张)。 互联网金融(电子账户和实名认证)。把银行账户体系电子化了。 货币最终是由国家发行的,铸币权是国家权力的体现。后来出现电子化货币,简化了票据类银行业务。 支付基础概念 电子支付是在付款银行和收款银行之间的货币债权转移。 支付体系的构成—基于银行卡体系的四方模式: 发卡方(服务商户,提供银行卡/二维码) 商户 收单方(服务商户。老式的 pos 机是要拓片留印记的。pos...
破解本博客不能部署的问题
试着生成公钥,然后一定要记得把 pubkey 粘贴到 github 的 setting 里然后用ssh ping github ssh -T git@github.com,即使返回错误也不要紧。 改用这个github 的部署地址:repo: git@github.com:magicliang/magicliang.github.io。
CMD 与 ENTRYPOINT
CMD 与 ENTRYPOINT 都是为了让容器工作得像可执行文件一样,接受参数,产生特定的输出存在的—容器命令化工具。如果没有这些工具,那么docker run -it abc:v0.0.1 /bin/bash 的最后一个参数就会变成启动命令。如果有CMD,它的命令也会被 docker run 结尾的参数命令锁覆盖,原本的命令不会作为 startup command 执行;如果有 ENTRYPOINT,docker run 结尾的参数命令会作为 ENTRYPOINT 的命令执行; CMD 还可以为 ENTRYPOINT 提供参数。 比较奇怪的地方是,如果使用了非 /bin/bash 的 startup command,docker run 的时候就不能 /bin/bash 进去了。 一个容器最好只有一个 CMD,一个 ENTRYPOINT。子容器的 CMD 会覆盖父容器的 CMD。 CMD 可以为 ENTRYPOINT 提供参数。 他们都有 exec 和...
Linux hypervisor
hypervisor 可以被认为等于 virtual hardware。他们的出现,可以有效减少硬件服务器数量。 常见的 hypervisor 分成两类: 直接运行在硬件上的,基于内核的虚拟机。 OS as hypervisor。典型例子是 KVM。KVM 是被集成到 Linux 内核之中的完整虚拟化解决方案。 运行于另一个操作系统之上。典型的例子是 QEMU 和 WINE。 hypervisor的实现,总是要映射一些磁盘设备和网络设备的。
MariaDB 调优相关
本文主要摘译自这里。 MySQL 曾经有独立的公司。但那间公司后来被 Sun 微系统公司获取了。 Sun 微系统公司又被 Oracle 获取了。原 MySQL 开发者担心 MySQL 成为闭源软件,因此成立了一家SkySQL 公司维护开源的 MySQL 分支—MariaDB。 MariaDB 支持的存储引擎包括: InnoDB/XtraDB 后者是前者的加强版,属于事务性存储引擎,也叫 ACID-compliant(ACID 遵从的)。XtraDB 是 Percona 开发的存储引擎,整体向下兼容。使用普通的 mysqldump 会耗尽 cpu(因为要把数据库转化成正经的 SQL 语句)。而 xtrabackup 在大库上的备份、还原、冗余都表现得更好(因为像 Oracle 一样是二进制备份吗?)。 TokuDB。另一个事务性存储引擎。以高压缩率著称(最高25倍压缩)。适合小空间存储大数据。 MyISAM。MySQL 上最古老的存储引擎。非事务性存储引擎,只支持表级锁,不支持...
KOA 初探
KOA 是 express 的进化版。都是被作者玩腻了扔掉的东西。 它简化了各个中间件层面的工作,提供了高级的“糖”,把各个中间件转化为了函数。 123456789101112131415161718192021222324252627282930313233const Koa = require('koa');const app = new Koa();// x-response-timeapp.use(async (ctx, next) => { const start = Date.now(); // 到这里就停住了运行,让下一个中间件函数运行。 await next(); // 从下一个中间件函数那里返回 const ms = Date.now() - start; ctx.set('X-Response-Time', `${ms}ms`);});// loggerapp.use(async (ctx,...
线程安全与锁优化
线程安全什么是线程安全“当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。” 相对的线程安全,可以分成五个等级: 线程安全的分类不可变不可变的数据,都是线程安全的。不可变的对象引用,加上所有field都是不可变的。如果有得选,尽量连方法都是final的。 绝对线程安全Vector不是线程安全的。它也会出现并发修改时 Out of Range 的异常(注意,不是 ConcurrentModification 的异常)。 相对线程安全需要保证对这个对象的单独操作是线程安全的,在调用的时候不需要加上额外的保障措施。对于特定顺序的连续操作,就需要额外的同步来保证调用的正确性了。 线程兼容可以通过特殊手段做到线程安全的普通类,绝大部分类都属于相对线程安全的。 线程对立线程对立,是不管调用端是否采取了同步措施,都无法在多线程环境中使用的代码。常见的线程对立的操作还有 suspend(),resume(),...