分布式事务知识小结

部分内容整理自:

面试必问:分布式事务六种解决方案 - 知乎 (zhihu.com)
10分钟说透Saga分布式事务 - 云+社区 - 腾讯云 (tencent.com)

1. 事务的ACID

  • 原子性(Atomicity),可以理解为一个事务内的所有操作要么都执行,要么都不执行。
  • 一致性(Consistency),可以理解为数据是满足完整性约束的,也就是不会存在中间状态的数据,比如你账上有400,我账上有100,你给我打200块,此时你账上的钱应该是200,我账上的钱应该是300,不会存在我账上钱加了,你账上钱没扣的中间状态。
  • 隔离性(Isolation),指的是多个事务并发执行的时候不会互相干扰,即一个事务内部的数据对于其他事务来说是隔离的。
  • 持久性(Durability),指的是一个事务完成了之后数据就被永远保存下来,之后的其他操作或故障都不会对事务的结果产生影响。

2. Redis的事务

阅读更多

Redis知识小结

部分内容整理自:

https://www.cnblogs.com/yiwangzhibujian/p/7047458.html
https://blog.csdn.net/striveb/article/details/95110502
https://mp.weixin.qq.com/s/2OTVJUTLOetYTD4Hpk-hFA
https://juejin.cn/post/6844903663224225806

1. Redis为啥这么快

  • 纯内存操作

    • Redis是一个KV内存数据库,它内部构建了一个哈希表,根据指定的KEY访问时,只需要O(1)的时间复杂度就可以找到对应的数据。同时,Redis提供了丰富的数据类型,并使用高效的操作方式进行操作,这些操作都在内存中进行,并不会大量消耗CPU资源,所以速度极快。image-20210929151720644

      image-20210929152137061

  • 单线程

    • Redis Server是多线程的,只是它的请求处理整个流程是单线程处理的
    • 单线程的方式是无法发挥多核CPU 性能,不过可以通过在单机开多个Redis 实例来完善
    • 优势
      • 没有了多线程上下文切换的性能损耗
      • 没有了访问共享资源加锁的性能损耗
      • 开发和调试非常友好,可维护性高
    • 缺点
      • 单线程处理最大的缺点就是,如果前一个请求发生耗时比较久的操作,那么整个Redis就会阻塞住,其他请求也无法进来,直到这个耗时久的操作处理完成并返回,其他请求才能被处理到。
  • 使用IO多路复用技术

    • 这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。
    • Redis采用了IO多路复用技术和非阻塞IO,这个技术由操作系统实现提供,Redis可以方便地操作系统的API即可。Redis可以在单线程中监听多个Socket的请求,在任意一个Socket可读/可写时,Redis去读取客户端请求,在内存中操作对应的数据,然后再写回到Socket中。
    • 多路I/O复用模型是利用select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
  • 非CPU密集型任务

    • 采用单线程的缺点很明显,无法使用多核CPU。Redis作者提到,由于Redis的大部分操作并不是CPU密集型任务,而Redis的瓶颈在于内存和网络带宽。
    • 如果你觉得单个Redis实例的性能不足以支撑业务,Redis作者推荐部署多个Redis节点,组成集群的方式来利用多核CPU的能力,而不是在单个实例上使用多线程来处理。

2. Redis架构

阅读更多

MySQL锁、索引、日志知识小结

1. myisam和innodb区别

  • myisam是MySQL 5.1以前的默认引擎,支持全文检索、压缩、空间函数等,但是不支持事务和行级锁,所以一般用于有大量查询少量插入的场景来使用,而且myisam不支持外键,并且索引和数据是分开存储的。
  • innodb是基于聚簇索引建立的,和myisam相反它支持事务、外键,并且通过MVCC来支持高并发,索引和数据存储在一起。

2. MySQL的索引

  • B+树和Hash索引

  • B+树是左小右大的顺序存储结构,节点只包含id索引列,而叶子节点包含索引列和数据,这种数据和索引在一起存储的索引方式叫做聚簇索引,一张表只能有一个聚簇索引。假设没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有的话则会隐式定义一个主键作为聚簇索引

    image-20210929154403899

  • 非聚簇索引(二级索引)保存的是主键id值,这一点和myisam保存的是数据地址是不同的

    image-20210929154445643

  • 区别
    image-20210929154500925

3. 覆盖索引和回表

阅读更多

MQ消息队列知识小结

1. MQ解决的问题

  • 解耦
    • 不用MQ:要针对各业务方开发,要考虑中断、超时、重试
    • 使用MQ:消息中间件类似一个代理,各业务方的通讯协调均由MQ负责,MQ来实现超时、重试机制
  • 异步
    • 不用MQ:长活同步事务,高延时,体验极差
    • 使用MQ:分步异步执行,防止同步阻塞
  • 削峰
    • 不用MQ:请求并发,服务器或数据库压力过大,导致宕机
    • 使用MQ:请求并发转串行,MQ来承担压力,平缓输出给服务器或数据库

2. 引入MQ产生的问题

  • 可用性
    • MQ挂了,整个系统都不能用
  • 复杂性
    • 消息重复:多次生产、多次消费
    • 消息乱序:新数据被旧数据覆盖
    • 消息丢失:漏数据、磁盘满了丢数据
  • 一致性
    • 分布式一致性问题,异步的多个事务没有最终都执行或都不执行

3. 常用MQ对比

阅读更多

基于阿里云IoT平台的物联网解决方案

去年差不多也是这个时候,我写过一篇《阿里云IoT应用案例》,重点提到了我们对于阿里云IoT SDK的封装并实现自主注册、消息队列规则转发、双向通讯、远程升级和远程控制等功能的设计思路。

又经过一年的持续优化、打磨,我们也落地了一整套物联网解决方案,包括物联网中间件和物联网平台,实现从仪器研发人员快速接入,到运维人员扫码装机注册,到仪器自动数据回传,到运维人员远程升级,再到管理人员物联网卡充值续费,最后到面向经营决策人员的大数据分析应用,拉通了整个业务闭环。

1. 背景

再一次提到背景,在上一篇文章中,简单概述了我们的物联网项目背景和需求,是为了解决在不同操作系统、不同开发语言的仪器,不同通讯协议、不同运营商的平台服务的环境下做一站式解决方案。但这只是技术背景和技术需求,放大来说,促使我们做这件事的原因还是产业数字化升级转型的趋势。一方面通过物联网和大数据等新技术对现有产品的升级、改造、赋能,让机器活起来,让数据流动起来,起到降本增效,辅助决策的作用,这是短期价值;另一方面,通过新技术的结合,面向新的场景探索,完成产品和业务的重塑,实现业务模式的转型,这是长期价值。

引用三个大佬的话来说这件事:

阅读更多

阿里云IoT应用案例

最近半年一直在尝试物联网相关技术在传统行业的应用,推动企业数字化转型。结合阿里云和阿里云IoT平台,初步实现了几个主要业务功能,整理分享如下:

1. 背景

核心诉求是终端设备接入物联网:一方面是为了数据的远程交互,另一方面是数据的收集和应用

目前终端种类繁多,未统一平台和标准,操作系统覆盖Windows、Android、Linux. 而IoT模组又依据主流通讯技术分成2G、3G、4G和NB-IoT,不同通讯技术的模组使用的协议不尽相同,这对于终端仪器开发的同学来说是个痛点,各个操作系统和开发语言均需对接IoT模组,一旦模组被更换,又需要重新匹配新的协议。

数据接收端也不好过,不同的运营商有自己的IoT平台,管理物联网卡和数据收发。更有运营商强制要求指定型号的模组只能用自家平台进行数据管理(如移远 BC95-5 只能使用电信Easy IoT平台)。应用系统开发需要维护多个运营商IoT平台,接口亦需开发多套。

阅读更多

《阿里巴巴中台战略思想与架构实践》笔记

1. 共享服务体系搭建

  • ESB解决异构系统之间的交互
  • 去中心化分布式服务框架除了对于 SOA 特性的实现和满足外,相比中心化服务架构最重要的不同就是服务提供者和服务调用者之间在进行服务交互时无需通过任何 服务路由中介, 避免因为中心点带来平台能力难扩展问题,以及潜在的雪崩影响
  • 关于雪崩
    • 企业服务总线架构一旦遇到上面所提到的“雪崩”事故后,故障恢复的时间和成本都非常高昂。因为传统的一台一台重启服务器已经不能进行故障的恢复,因为一旦服务启动起来,前端的访问洪流会立即再次压垮启动后的服务器,唯一正确的方式则是首先切断前端应用对企业服务总线的服务请求,让这10台服务器全部启动后,再开放服务请求,这样才能恢复系统的运行。但因为着急恢复系统,没有来得及定位之前造成开始服务实例出问题的根本原因,这样的系统恢复运行其实处于一个“脆弱”的状态,之前造成服务实例宕机的问题可能让“雪崩”事故再次上演。
  • 微服务架构的典型特征
    • 分布式组成的系统
    • 按照业务划分也不是按照技术划分
    • 做有生命的产品而不是项目
    • 智能化服务端点与傻瓜式服务编排
    • 自动化运维
    • 系统容错
    • 服务快速演化
  • 关于微服务的”微”
    • “微服务”中的这个“微”字给很多人带来了很多误解。从字面意思上,“微”会让人联想到一个微服务就应该是功能足够单一,甚至出现一个服务的实现可能只需要几十或者上百行代码的说法,这应该是最误导人的观点。从技术角度出发,确实可以通过简短的代码实现功能单一的服务,但从一个整体架构考虑,如果是以这样的方式实现各个微服务,则在整个服务体系范畴当中包含太多功能边界,那么对于服务运营的分工和边界就很难界定,给服务接下来的持续运营和维护带来困扰;另外拆分过于细化的服务,势必将带来大量无谓的分布式事务调用,给业务的实现带来额外的工作量和风险。

2. 服务中心建设

  • 服务中心一定是不断发展的
  • 尝试服务化 - 全面服务化 - 服务平台化
  • 服务中心的多样性
    • 接口:API
    • 工具:配置服务、管理服务
    • 数据:大数据分析
  • 服务中心可以进一步划分
  • 服务中心和业务不一定一一对应
  • 服务中心划分原则
    • 三个方面
      • 设计
      • 运营
      • 工程
    • 四个原则
      • 高内聚低耦合
      • 数据完整性
      • 业务可运营
      • 持续渐进

3. 数据拆分

阅读更多

浅谈数字化转型

我们探讨数字化生存,数字化转型,那么何为数字化转型?为什么要转型?如何去做转型?这是我们探讨话题的最根本的问题。我将结合自身工作经验和行业案例,浅谈这三个问题,旨在抛砖引玉。

什么是数字化转型

​ 我们谈转型,这是一个过程,有始有终。那么数字化转型是从哪转到哪?一般来讲,我们认为是从信息化技术也就是IT,转型到数字化技术DT.

​ IT与DT最直观的区别是,IT是落后于需求的,而DT是领先于需求的。如何理解这一说法,这里举一个例子:

  • 信息化时代,企业上OA、ERP、CRM等信息化系统,一般采用外购软件或者第三方现场实施,要求通过信息化系统满足和适配工作中现有的实际需求,且大部分情况是一锤子买卖。但业务不是一成不变,当需求发生改变时,大多数企业选择的是忽略改变或者越过系统,这就导致在2018年以前,绝大部分上信息化系统的企业,包括政府机关,他们的信息化推进极为缓慢。在IT阶段中,业务与技术分离,技术人员处于支持者的角色。企业需要什么,IT就做什么,这就是为什么IT是落后于需求。
  • 数字化时代,企业有团队有能力自己搭建开发信息化系统,并根据业务发展持续不断的优化完善系统。积累大量数据,通过BI、AI手段指导市场和探索新业务。最近几年,云服务商直接与政府合作,广东、杭州开展的一系列数字政务都能让大家感受到数字化时代快速发展的力量。几乎在一夜之间,社保公积金可以刷脸查询;身份证明、婚姻证明可以联网互通;异地可以办理出入境等等。在DT阶段,技术人员以运营作为首要目标和角色。能通过数字化手段帮企业做啥,这就是为什么说DT领先于需求。
阅读更多

在Kubernetes上搭建RabbitMQ Cluster

为了在Kubernetes上搭建RabbitMQ3.7.X Cluster,踩爆无数坑,官方整合了第三方开源项目但没有完整demo,网上的post都是RabbitMQ 3.6.X旧版的部署方案,几经周折,最终弄明白在Kubernetes集群下,基于Kubernetes Discovery,使用hostname方式部署RabbitMQ3.7.X Cluster,总结如下:

1. IP模式

rabbitmq-peer-discovery-k8s是RabbitMQ官方基于第三方开源项目rabbitmq-autocluster开发,对3.7.X版本提供的Kubernetes下的同行发现插件,但官方只提供了一个基于IP模式的demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
kind: Service
apiVersion: v1
metadata:
namespace: test-rabbitmq
name: rabbitmq
labels:
app: rabbitmq
type: LoadBalancer
spec:
type: NodePort
ports:
- name: http
protocol: TCP
port: 15672
targetPort: 15672
nodePort: 31672
- name: amqp
protocol: TCP
port: 5672
targetPort: 5672
nodePort: 30672
selector:
app: rabbitmq
---
apiVersion: v1
kind: ConfigMap
metadata:
name: rabbitmq-config
namespace: test-rabbitmq
data:
enabled_plugins: |
[rabbitmq_management,rabbitmq_peer_discovery_k8s].
rabbitmq.conf: |
## Cluster formation. See http://www.rabbitmq.com/cluster-formation.html to learn more.
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_k8s
cluster_formation.k8s.host = kubernetes.default.svc.cluster.local
## Should RabbitMQ node name be computed from the pod's hostname or IP address?
## IP addresses are not stable, so using [stable] hostnames is recommended when possible.
## Set to "hostname" to use pod hostnames.
## When this value is changed, so should the variable used to set the RABBITMQ_NODENAME
## environment variable.
cluster_formation.k8s.address_type = ip
## How often should node cleanup checks run?
cluster_formation.node_cleanup.interval = 30
## Set to false if automatic removal of unknown/absent nodes
## is desired. This can be dangerous, see
## * http://www.rabbitmq.com/cluster-formation.html#node-health-checks-and-cleanup
## * https://groups.google.com/forum/#!msg/rabbitmq-users/wuOfzEywHXo/k8z_HWIkBgAJ
cluster_formation.node_cleanup.only_log_warning = true
cluster_partition_handling = autoheal
## See http://www.rabbitmq.com/ha.html#master-migration-data-locality
queue_master_locator=min-masters
## See http://www.rabbitmq.com/access-control.html#loopback-users
loopback_users.guest = false

---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: rabbitmq
namespace: test-rabbitmq
spec:
serviceName: rabbitmq
replicas: 3
template:
metadata:
labels:
app: rabbitmq
spec:
serviceAccountName: rabbitmq
terminationGracePeriodSeconds: 10
containers:
- name: rabbitmq-k8s
image: rabbitmq:3.7
volumeMounts:
- name: config-volume
mountPath: /etc/rabbitmq
ports:
- name: http
protocol: TCP
containerPort: 15672
- name: amqp
protocol: TCP
containerPort: 5672
livenessProbe:
exec:
command: ["rabbitmqctl", "status"]
initialDelaySeconds: 60
periodSeconds: 60
timeoutSeconds: 10
readinessProbe:
exec:
command: ["rabbitmqctl", "status"]
initialDelaySeconds: 20
periodSeconds: 60
timeoutSeconds: 10
imagePullPolicy: Always
env:
- name: MY_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: RABBITMQ_USE_LONGNAME
value: "true"
# See a note on cluster_formation.k8s.address_type in the config file section
- name: RABBITMQ_NODENAME
value: "rabbit@$(MY_POD_IP)"
- name: K8S_SERVICE_NAME
value: "rabbitmq"
- name: RABBITMQ_ERLANG_COOKIE
value: "mycookie"
volumes:
- name: config-volume
configMap:
name: rabbitmq-config
items:
- key: rabbitmq.conf
path: rabbitmq.conf
- key: enabled_plugins
path: enabled_plugins

在ConfigMap配置项中,指明 cluster_formation.k8s.address_type = ip,也就是说RabbitMQ Node的命名和访问地址是以IP地址作为区分,如rabbit@172.0.5.1

阅读更多

阿里云Kubernetes实战3--DevOps

前言:

在上一篇文章中,我们已经在K8S集群部署了Jenkins、Harbor和EFK。作为本系列最后一篇文章,将通过实际案例串联所有的基础软件服务,基于K8S做DevOps。

整体的业务流程如下图所示:

1

一、一机多Jenkins Slave

阅读更多