====================
== Hi, I'm Vimiix ==
====================
Practice makes perfect (ง •̀_•́)ง

分布式事务笔记(XA,TCC,Saga)

distributed note
基础理论 CAP理论 一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。这被称为CAP理论,已经被证实。 一致性(Consistency) :在分布式系统中所有的数据备份,在同一时刻都保持一致状态,如无法保证状态一致,直接返回错误。 可用性(Availability):在集群中一部分节点故障,也能保证客户端访问系统并得到正确响应,允许一定时间内数据状态不一致。 分区容错性(Partition tolerance):分布式系统在遇到任何网络分区故障时,仍然能保证对外提供满足一致性和可用性的服务,除非整个网络环境都发生故障。 ACID特性(刚性事务,强一致性) 把多条语句作为一个整体进行操作的功能,称为数据库事务。数据库事务可以确保该事务范围内的所有操作全部成功或者全部失败。 事务具有 4 个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为 ACID 特性。 原子性(Atomicity):一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。 事务隔离(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括未提交读(Read uncommitted)、提交读(read committed)、可重复读(repeatable read)和串行化(Serializable)。 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。 BASE理论(柔性事务) BASE是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的简写,BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency) 基本可用(Basically Available):是指分布式系统在出现不可预知故障的时候,允许损失部分可用性——但请注意,这绝不等价于系统不可用。 软状态(Soft state):和硬状态相对,是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。 最终一致性(Eventually consistent):强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。 总的来说,BASE理论面向的是大型高可用可扩展的分布式系统,和传统事务的ACID特性使相反的,它完全不同于ACID的强一致性模型,而是提出通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。但同时,在实际的分布式场景中,不同业务单元和组件对数据一致性的要求是不同的,因此在具体的分布式系统架构设计过程中,ACID特性与BASE理论往往又会结合在一起使用。 分布式方案 XA规范 Open Group组织定义的一套DTP(Distributed Transaction Processing)分布式事务处理模型,主要包含以下四部分: AP(应用程序) TM(事务管理器):中间件,负责多个事物之间的协调 RM(资源管理器):数据库等资源 CRM(通信资源管理器):消息中间件 XA规范包括两套函数,分别以 xa_ 和 ax_ 开头,使 TM 可以对 RM 进行的操作: xa_open,xa_close:建立和关闭与资源管理器的连接; xa_start,xa_end:开始和结束一个本地事务; xa_prepare,xa_commit,xa_rollback:预提交、提交、回滚一个本地事务; xa_recover:回滚一个已进行预提交的事务; ax_开头的函数使资源管理器可以动态地在事务管理器中进行注册,并可以对XID(TRANSACTION IDS)进行操作; ax_reg,ax_unreg;允许一个资源管理器在一个TMS(TRANSACTION MANAGER SERVER)中动态注册或撤消注册。 基于XA规范衍生出下面的两阶段提交(2PC)、三阶段提交(3PC)。 Read more...

磁盘只读(readonly)故障场景模拟

disk simulate test
假设服务器目前有多个盘,vdb1这块分区盘专门用于数据库程序的数据目录,我们就用 vdb1 这个盘来模拟只读故障场景。 1. 卸载指定盘 umount /dev/vdb1 想要如期卸载掉,需要确保该盘上没有被正在运行进程依赖,如果有运行中的进程依赖这个盘,会报如下报 target is busy 的错误: umount: /opt: target is busy. 遇到该错误时,可以通过lsof [mountpoint] 命令来查看有哪些进程依赖这块盘,kill 掉相应的进程后重新卸载。 2. 配置伪设备来镜像 /dev/vdb1 的内容 卸载成功后,我们通过 losetup 指令来配置一个loop设备(在类 UNIX 系统里,loop 设备是一种伪设备(pseudo-device),或者也可以说是仿真设备。它能使我们像块设备一样访问一个文件)。 losetup /dev/loop0 /dev/vdb1 执行指令后,可以通过 losetup -l 查看当前服务器上的 loop 设备列表: 3. 挂载 /dev/loop0 我们已经有一个 /dev/loop0 的伪设备镜像到了 /dev/vdb1 上,此时,我们来挂载 /dev/loop0 这个伪设备: mount /dev/loop0 /opt -o rw,errors=remount-ro 通过 df -h 可以查看到 /dev/loop0 已经正常挂载上了 4. Read more...

使用SQLAlchemy以多IP方式连接openGauss数据库

SQLAlchemy Python openGauss
前置声明 由于 openGauss 数据库本身也开源不久,所以周边基础设施也正处于遍地开花的阶段,所以本文不保证长期的时效性,仅针对现阶段的问题,提出一种解决方案。 openGauss 介绍 按照官网的介绍,openGauss 是一款高性能,高安全,高可靠的开源关系型数据库管理系统,采用木兰宽松许可证v2发行。openGauss内核早期源自开源数据库PostgreSQL,融合了华为在数据库领域多年的内核经验,在架构、事务、存储引擎、优化器及ARM架构上进行了适配与优化。 openGauss 在2020年6月30日开放源代码,代码托管在 gitee 上。 目前我所在公司也主要是做数据库方面的事情,且也基于 openGauss 内核研发了一款商业版的数据库 MogDB,感兴趣的也可以去了解一下。 背景 针对 openGauss 的基础设施不完善,我之前基于 py-postgresql 1.3.0 版本,开发了 openGauss 的 python 驱动,并提交到了 openGauss 官方仓库:https://gitee.com/opengauss/openGauss-connector-python-pyog 该驱动适用于不使用 ORM,以SQL形式交互的 python 程序。 但是在对接客户的过程中,客户提出了这样的需求: 程序中用到了 SQLAlchemy 做为ORM来和数据库交互 连接数据库时,需要支持类似 JDBC 多 IP 的方式连接(例如:user:password@host1:port1,host2:port2/db 这种形式),这种需求主要是用于后端数据库部署形态为主备架构,且没有固定的虚拟IP用于连接,所以需要将主备所有机器的IP都传递进去,但只能返回主库的连接。 赶紧去扫了一下 SQLAlchemy 的源码,SQLAlchemy 中目前支持的 pg 驱动有: psycopg2 pg8000 asyncpg psycopg2cffi py-postgresql pygresql 其实只要在驱动里面实现了 PEP-249 (DBAPI 2.0 接口规范) 就可以。但是我们都知道,在使用 SQLAlchemy 创建 engine 的时候,需要在 :// 前面使用固定的字符串进行驱动的选择。比如 postgresql+pypostgresql://. Read more...

Golang的并行模式实践

concurrency golang goroutine
Goroutine C#、Lua、Python 的用户可能会发现 Go 的 goroutine 和协程之间有很多相似之处,没错,从命名上也可以看出二者具有相似性。 但二者之间也有些区别: goroutine 隐含了并行的特性,一切交给 go 的 runtime 来实现调度,而协程需要应用自己来编写并行代码 goroutine 通过信道(Channel)进行通信;协程通过 yield 和 next操作进行通信 一般来说,goroutine 比协程更强大。而且,我们可以很容易地将协程的逻辑移植到 goroutine 来获得更好的并行效果。 Generators 在 python 中,要实现一个生成器,需要通过 yield 生成数据,通过 next 获取数据: def integers(): i = 1 while True: yield i i+=1 integerGenerator = integers() next(integerGenerator) # 1 next(integerGenerator) # 2 next(integerGenerator) # 3 同样的,生成器也可以在 Go 中实现,只是使用了 channel 来代替 yield: func integers () chan int { yield := make (chan int); count := 0; go func () { for { yield <- count; count++; } } (); return yield } next := integers(); func generateInteger () int { return <-next } generateInteger() // 0 generateInteger() // 1 generateInteger() // 2 Iterators go 的 channel 在语法层面就是天然的迭代器。 Read more...

Golang实现Windows系统用户和密码校验

note windows golang
本质上是通过调用 windows 的一个 API —— LogonUserW ,来实现对于用户密码的校验。 仅适用于在本地校验,不支持远程连接校验 用一个示例代码来进行说明,下面是目录结构中,main.go 是程序入口文件,auth 包中,我们仅实现 windows 系统的校验代码,其他平台不属于本文介绍内容,就直接返回 nil 即可。 目录结构 . ├── auth │ ├── auth.go │ └── auth_windows.go ├── go.mod └── main.go 源代码 [src] main.go package main import ( "flag" "fmt" "os" "github.com/vimiix/authDemo/auth" ) func main() { user := flag.String("u", "", "username") password := flag.String("p", "", "password") flag.Parse() if *user == "" || *password == "" { fmt.Println("Both user and password should be specify") fmt. Read more...

beanstalkd消息队列

beanstalkd note Python MQ
beanstalkd 是一个简单快速的分布式工作队列系统,协议基于 ASCII 编码运行在 tcp 上。其最初设计目的是通过后台异步执行耗时任务方式降低高容量 Web 应用的页面延时。而其简单、轻量、易用等特点,和对任务优先级、延时/超时重发等控制,以及众多语言版本的客户端的良好支持,使其可以很好的在各种需要队列系统的场景中应用。 Beanstalk 的应用场景主要有: 消息异步处理(消息队列的基本需求) 消息延迟处理,实现循环队列 beanstalkd 核心组件 job : 任务,队列中的基本单元 tube : 一个有名称的任务队列,用来存储统一类型的 job ,beanstalkd 通过 tube 来实现多任务队列 producer : job 生产者,通过put命令来创建一个job放到一个tube中 comsumer : job 消费者,通过 reserve、release、bury、delete命令来获取或改变 job 的状态 job 的生命周期 在整个生命周期中 job 可能有四种工作状态:READY、RESERVED、DELAYED、BURIED. 只有处于 READY 状态的 job 才能被消费。 put with delay release with delay -------------> [DELAYED] <---------. | | | (time passes) | | | put v reserve | delete --------------> [READY] -------> [RESERVED] ------> *poof* ^ ^ | | | \ release | | | `-------------' | | | | kick | | | | bury | [BURIED] <---------------' | | delete `--------> *poof* Producer 创建 job 的时候可以选择两种方式:put , put with delay。 Read more...

[译]Richardson成熟度模型

translation Richardson
原文链接:https://martinfowler.com/articles/richardsonMaturityModel.html 迈向 REST 的荣耀之巅 Leonard Richardson 提出的一个模型,将实现 REST 方法的主要元素分解为三个步骤,分别包括:资源(Resources)、HTTP 动词(HTTP Verbs,如GET、POST等)和超媒体控制(Hypermedia Controls)。 在Rest In Practice一书中,解释了如何使用 Restful Web Service 来处理企业面临的许多集成问题。本书的核心观点是,Web 就是一个大规模可扩展的分布式系统存在、并可以很好的工作的证明,而我们可以根据这一观点更容易地构建集成系统。 为了说明一个“Web 风格”系统的特定属性,作者使用了由 Leonard Richardson 提出的“RESTful 成熟度模型”,该模型在一次QCon Talk中被谈到。通过这一模型,可以很好的思考如果使用 REST,所以我也会尝试添加一些自己的解释。(本文中所使用协议示例只是为了更好的说明,并不建议在实际生产中编码实现或测试,因为其在细节上可能会存在问题) Level 0 该模型的出发点是使用 HTTP 作为远程交互的传输系统,但不使用 Web 的任何机制。基本上就是使用 HTTP 作为你远程交互机中的隧道机制,通常基于“远程过程调用”(RPC,Remote Procedure Invocation)。 例如,我想预约我的医生。预约软件首先需要知道在指定日期内医生什么时间有空位,所以它需要向医院预约系统发送请求以获取该信息。在 Level 0 级场景中,医院会将某个 URI 做为一个公共服务点。然后,我就可以向该服务点发送一个文档请求。 POST /appointmentService HTTP/1.1 [various other headers] <openSlotRequest date="2010-01-04" doctor="mjones" /> 然后,服务器会返回一个我所需信息的文档: HTTP/1.1 200 OK [various headers] <openSlotList> <slot start="1400" end="1450"> <doctor id="mjones" /> </slot> <slot start="1600" end="1650"> <doctor id="mjones" /> </slot> </openSlotList> 在本例中我使用了 XML 做为内容格式,实现可以格式的,如:JSON、YAML、键-值对、或其它自定义格式。 Read more...

Golang实现Google在RTB广告中价格加密方案

solution golang rtb
RTB RTB 广告是一种实时竞价广告,就是在针对每个广告位有展示机会的时候,会实时多方竞价,价格最有优势的广告主会竞得这次展示机会,在媒体测在拿到素材的时候,需将本次成交的价格,上报给指定的监控服务器,这时就需要将实时价格按照指定的加密方案加密后,替换 GET 链接中的请求参数中的价格宏来上报。 官方给出的源代码有 Java 和 C++ 版本, 下载地址: https://code.google.com/archive/p/privatedatacommunicationprotocol/source/default/source 本文主要通过 golang 来实现的 google 的价格加密方案。 Source Code package main /* golang 实现 google 的rtb 价格加密方案 https://developers.google.com/authorized-buyers/rtb/response-guide/decrypt-price#encryption-scheme */ import ( "crypto/hmac" "crypto/md5" "crypto/sha1" "encoding/base64" "encoding/binary" "encoding/hex" "fmt" "hash" "math" "strings" ) const ( PayloadSize = 8 InitVectorSize = 16 SignatureSize = 4 EKey = "" IKey = "" UTF8 = "utf-8" ) func AddBase64Padding(base64Input string) string { var b64 string b64 = base64Input if i := len(b64) % 4; i ! Read more...

Mac 升级10.12.6 mvim 打开文件报错

solution mac mvim
当昨天把 Mac 升级了 10.12.6 Sierra 以后,mvim 打开文件的时候就开始报错,使用该方法已解决~ 报错信息 dyld: Library not loaded: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/libruby.2.0.0.dylib Referenced from: /usr/local/Cellar/macvim/8.0-146/MacVim.app/Contents/bin/../MacOS/Vim Reason: image not found [1] 33114 abort mvim -v 解决方法 这个错误是 macvim 报的错,并非 vim. ➜ vimiix ~ type vim vim is an alias for mvim -v 我这里使用的 vim 指令是对 mvim 的一个别名。 使用一条指令可以解决上面的报错问题: sudo install_name_tool -change /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/libruby.2.0.0.dylib /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/libruby.2.3.0.dylib /usr/local/Cellar/macvim/8.0-146/MacVim.app/Contents/bin/../MacOS/Vim 注意点 需要注意的是,指令最后指定的 vim 路径,一定是上面报错中 Referenced from 后面的路径。参考 相关解答 https://stackoverflow.com/questions/47278449/vim-ruby-mismatch-on-mac-high-sierra

Golang如何确保一个类型实现了某个interface

note interface golang
在 golang 中,接口(interface)代表一种『协议』存在,它是一个声明了多个方法的集合。 接口是被隐式实现的,也就是说,我们在开发中定义一个类型(type)的时候,不需要声明这个类型实现了哪个接口。在使用的时候往往通过断言来的 ok-idom 来进行类型判断该类型是否实现了目标接口,放置调用方法失败抛出 panic: if value, ok := AType.(BInterface) { fmt.Println("ok") } else { fmt.Println("no") } 如果断言失败,那么 ok 的值将会是 false,但是如果断言成功 ok 的值将会是 true,同时 value 将会得到所期待的正确的值。 但是,在某些情况下,我们可能希望明确地检查接口中哪些方法没有被实现。最好的方法就是借助编译器地检查功能。 假设定义了一个 Programmer 接口,一个 Human 类型: »> 试一下 package main type Programmer interface { Code() string } type Human struct {} func main() {} 这段代码没有做任何操作,可以正常地执行。 假设我们希望 Human 类型实现了 Programmer 接口,可以在代码中定义一个 _ (下划线表示忽略这个变量)变量来实现检测效果 package main type Programmer interface { Code() string } type Human struct {} // 利用编译器检查接口实现 var _ Programmer = (*Human)(nil) func main() {} 当再次执行这段代码地时候,就会报出如下编译错误: Read more...
1 of 8 下一页