精华内容
下载资源
问答
  • 2021-07-26 03:31:43

    大家好,我是时间财富网智能客服时间君,上述问题将由我为大家进行解答。

    网关和ip地址不一样。网关(Gateway)又称网间连接器、协议转换器。网关在网络层以上实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。

    网关既可以用于广域网互连,也可以用于局域网互连。 网关是一种充当转换重任的计算机系统或设备。使用在不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。与网桥只是简单地传达信息不同,网关对收到的信息要重新打包,以适应目的系统的需求。同层、应用层。

    IP地址(Internet Protocol Address),全称为网际协议地址,是一种在Internet上的给主机编址的方式。它是IP协议提供的一种统一的地址格式,常见的IP地址分为IPv4与IPv6两大类,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。IP是英文Internet Protocol的缩写,意思是“网络之间互连的协议”,也就是为计算机网络相互连接进行通信而设计的协议。在因特网中,它是能使连接到网上的所有计算机网络实现相互通信的一套规则,规定了计算机在因特网上进行通信时应当遵守的规则。任何厂家生产的计算机系统,只要遵守IP协议就可以与因特网互连互通。正是因为有了IP协议,因特网才得以迅速发展成为世界上最大的、开放的计算机通信网络。因此,IP协议也可以叫做“因特网协议”。

    更多相关内容
  • 什么是一致性Hash算法?

    万次阅读 多人点赞 2018-03-13 21:15:32
    最近有小伙伴跑过来问什么是Hash一致性算法,说面试的时候被问到了,因为不了解,所以就没有回答上,问我有没有相应的学习资料推荐,当时上班,没时间回复,晚上回去了就忘了这件事,今天突然看到这个,加班为大家...

    最近有小伙伴跑过来问什么是Hash一致性算法,说面试的时候被问到了,因为不了解,所以就没有回答上,问我有没有相应的学习资料推荐,当时上班,没时间回复,晚上回去了就忘了这件事,今天突然看到这个,加班为大家整理一下什么是Hash一致性算法,希望对大家有帮助!

    经常阅读我文章的小伙伴应该都很熟悉我写文章的套路,上来就是先要问一句为什么?也就是为什么要有Hash一致性算法?就像以前介绍为什么要有Spring一样,首先会以历史的角度或者项目发展的角度来分析,今天的分享还是一样的套路,先从历史的角度来一步步分析,探讨一下到底什么是Hash一致性算法!

    一、Redis集群的使用

    我们在使用Redis的时候,为了保证Redis的高可用,提高Redis的读写性能,最简单的方式我们会做主从复制,组成Master-Master或者Master-Slave的形式,或者搭建Redis集群,进行数据的读写分离,类似于数据库的主从复制和读写分离。如下所示:
    这里写图片描述
    同样类似于数据库,当单表数据大于500W的时候需要对其进行分库分表,当数据量很大的时候(标准可能不一样,要看Redis服务器容量)我们同样可以对Redis进行类似的操作,就是分库分表。

    假设,我们有一个社交网站,需要使用Redis存储图片资源,存储的格式为键值对,key值为图片名称,value为该图片所在文件服务器的路径,我们需要根据文件名查找该文件所在文件服务器上的路径,数据量大概有2000W左右,按照我们约定的规则进行分库,规则就是随机分配,我们可以部署8台缓存服务器,每台服务器大概含有500W条数据,并且进行主从复制,示意图如下:

    这里写图片描述

    由于规则是随机的,所有我们的一条数据都有可能存储在任何一组Redis中,例如上图我们用户查找一张名称为"a.png"的图片,由于规则是随机的,我们不确定具体是在哪一个Redis服务器上的,因此我们需要进行1、2、3、4,4次查询才能够查询到(也就是遍历了所有的Redis服务器),这显然不是我们想要的结果,有了解过的小伙伴可能会想到,随机的规则不行,可以使用类似于数据库中的分库分表规则:按照Hash值、取模、按照类别、按照某一个字段值等等常见的规则就可以出来了!好,按照我们的主题,我们就使用Hash的方式。

    二、为Redis集群使用Hash

    可想而知,如果我们使用Hash的方式,每一张图片在进行分库的时候都可以定位到特定的服务器,示意图如下:

    这里写图片描述

    上图中,假设我们查找的是"a.png",由于有4台服务器(排除从库),因此公式为hash(a.png) % 4 = 2 ,可知定位到了第2号服务器,这样的话就不会遍历所有的服务器,大大提升了性能!

    三、使用Hash的问题

    上述的方式虽然提升了性能,我们不再需要对整个Redis服务器进行遍历!但是,使用上述Hash算法进行缓存时,会出现一些缺陷,主要体现在服务器数量变动的时候,所有缓存的位置都要发生改变!

    试想一下,如果4台缓存服务器已经不能满足我们的缓存需求,那么我们应该怎么做呢?很简单,多增加几台缓存服务器不就行了!假设:我们增加了一台缓存服务器,那么缓存服务器的数量就由4台变成了5台。那么原本hash(a.png) % 4 = 2 的公式就变成了hash(a.png) % 5 = ? , 可想而知这个结果肯定不是2的,这种情况带来的结果就是当服务器数量变动时,所有缓存的位置都要发生改变!换句话说,当服务器数量发生改变时,所有缓存在一定时间内是失效的,当应用无法从缓存中获取数据时,则会向后端数据库请求数据(还记得上一篇的《缓存雪崩》吗?)!

    同样的,假设4台缓存中突然有一台缓存服务器出现了故障,无法进行缓存,那么我们则需要将故障机器移除,但是如果移除了一台缓存服务器,那么缓存服务器数量从4台变为3台,也是会出现上述的问题!

    所以,我们应该想办法不让这种情况发生,但是由于上述Hash算法本身的缘故,使用取模法进行缓存时,这种情况是无法避免的,为了解决这些问题,Hash一致性算法(一致性Hash算法)诞生了!

    四、一致性Hash算法的神秘面纱

    一致性Hash算法也是使用取模的方法,只是,刚才描述的取模法是对服务器的数量进行取模,而一致性Hash算法是对232取模,什么意思呢?简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-232-1(即哈希值是一个32位无符号整形),整个哈希环如下:
    这里写图片描述
    整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、5、6……直到232-1,也就是说0点左侧的第一个点代表232-1, 0和232-1在零点中方向重合,我们把这个由232个点组成的圆环称为Hash环

    下一步将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置,这里假设将上文中四台服务器使用IP地址哈希后在环空间的位置如下:
    这里写图片描述
    接下来使用如下算法定位数据访问到相应服务器:将数据key使用相同的函数Hash计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器!

    例如我们有Object A、Object B、Object C、Object D四个数据对象,经过哈希计算后,在环空间上的位置如下:

    这里写图片描述
    根据一致性Hash算法,数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上。

    五、一致性Hash算法的容错性和可扩展性

    现假设Node C不幸宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到Node D。一般的,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响,如下所示:

    这里写图片描述

    下面考虑另外一种情况,如果在系统中增加一台服务器Node X,如下图所示:
    这里写图片描述
    此时对象Object A、B、D不受影响,只有对象C需要重定位到新的Node X !一般的,在一致性Hash算法中,如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它数据也不会受到影响。

    综上所述,一致性Hash算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

    六、Hash环的数据倾斜问题

    一致性Hash算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,例如系统中只有两台服务器,其环分布如下:
    这里写图片描述
    此时必然造成大量数据集中到Node A上,而只有极少量会定位到Node B上。为了解决这种数据倾斜问题,一致性Hash算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。具体做法可以在服务器IP或主机名的后面增加编号来实现。

    例如上面的情况,可以为每台服务器计算三个虚拟节点,于是可以分别计算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值,于是形成六个虚拟节点:
    这里写图片描述
    同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“Node A#1”、“Node A#2”、“Node A#3”三个虚拟节点的数据均定位到Node A上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。

    七、总结

    上文中,我们一步步分析了什么是一致性Hash算法,主要是考虑到分布式系统每个节点都有可能失效,并且新的节点很可能动态的增加进来的情况,如何保证当系统的节点数目发生变化的时候,我们的系统仍然能够对外提供良好的服务,这是值得考虑的!


    参考文章:

    1、https://www.cnblogs.com/lpfuture/p/5796398.html
    2、http://www.zsythink.net/archives/1182

    在这里插入图片描述

    【视频福利】2T免费学习视频,搜索或扫描上述二维码关注微信公众号:Java后端技术(ID: JavaITWork)回复:1024,即可免费获取!内含SSM、Spring全家桶、微服务、MySQL、MyCat、集群、分布式、中间件、Linux、网络、多线程,Jenkins、Nexus、Docker、ELK等等免费学习视频,持续更新!

    展开全文
  • 什么是一致性哈希?看这里

    千次阅读 多人点赞 2020-03-26 11:18:59
    2.1 一致性哈希 一致性 Hash 算法也是使用取模的思想,只是,刚才描述的取模法是对节点数量进行取模,而一致性 Hash 算法是对 2^32 取模,什么意思呢?简单来说,一致性 Hash 算法将整个哈希值空间组织成一个虚拟的...

    [TOC]

    前言

    伴随着系统流量的增大,出现了应用集群。在 Redis 中为了保证 Redis 的高可用也为 Redis 搭建了集群对数据进行分槽存放。在 Mysql 数据库要存储的量达到一个很高的地步的时候,我们会对数据库进行分库分表操作。OK,到这儿先假设我们不知道什么是集群、什么是分库分表,我们先来看一个数据库水平切分演变的例子:

    假设我们的系统中有一张会员表 customer_info, 我们的系统刚开始无人问津,我们在一个单个的数据库中放这张表,所有的会员记录都插入到这个数据库的这张表中,这没什么问题,是一个很正常且合理的操作。某段时间,我们的系统突然火爆了起来,注册会员激增,达到了千万级别并且还在快速增长,这时候所有的用户请求数据都会请求这张表,毫无疑问数据库的压力很大,于是可能会经常发生宕机事件,给系统造成了很大影响。为了解决这件事情,我们将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据不同。 这样做能够有效的缓解单机数据库的压力和系统的性能瓶颈。

    看完了这个例子,我们对水平拆分数据库有了一个大致的印象,其实就是把很多的数据按照一定的规则存放在不同的服务器上,然后查找的时候能够根据存放的时候的规则去找到前面存放的数据。那么我们要说的一致性哈希算法,其实就是解决了这里面的 存取规则 的问题,有了这个一致性哈希算法,我们能够准确的知道我们要取的数据落在哪个机器的哪个数据库中。

    1. 简单哈希

    还是上面水平拆分数据库的例子,假设我们现在不知道什么一致性哈希什么集群分槽,就让我们自己想的话,我们可以很容器的想到 java 中的 HashMap 的原理,它通过计算了一个 key 的哈希值,然后拿这个哈希值对底层数组取模就得到了一个哈希桶,如果数据存在的话,就一定在这个哈希桶里,否则就不存在。类似的可以想到,假设我们的 customer_info 我们可以按照用户 id 去分库分表,假设此时存在水平的三个库表,如下,我们分别称之为 节点 D1, 节点 D2, 节点 D0

    机器 ip 数据库数据表
    127.0.0.1customercustomer_info
    127.0.0.2customercustomer_info
    127.0.0.3customercustomer_info

    分库分表的时候,用户 A 的记录落在了 D1 机器,用户 B 的记录落在了 D2 机器,用户 C 的机器落在了 D0 机器上,用户 A 要存在哪条数据库上的计算过程是用户 A 的会员 id 的哈希值对 3 取模,因为现在只有 3 台机器,伪代码: A_id.hash() % / 3,用户 B 和用户 C 依次类推。如下图所示

    在这里插入图片描述

    这好像很方便的解决了存取规则的问题,我们来分析一波:
    假设我们的系统用户量又激增了,我们就需要再加一些机器,此时我们再计算哈希值的时候,取模不再是对 3 取模了,而是对 4 进行取模了,之前 A_id.hash() % / 3 = 1, 而现在 A_id.hash() % / 4 = ? 这个值很大概率不会是 1,所以这就会出现用户明明存在记录但是却查不到的情况,这就问题很大了,如果要解决这个问题只能在机器节点数量变化的时候对数据重新哈希,这代价就有点大了。所以,我们需要想办法让这种情况不发生,这种情况发生的根本是哈希算法本身的特性导致的,直接使用取模的话这是无法避免的。所以就有了一致性哈希

    2. 一致性哈希

    上面通过数据库的例子介绍了哈希算法,然后也分析了它的劣势,当机器数量发生变动的时候,几乎所有的数据都会移动 (不移动的应该是运气比较好吧前后取模都是同一个值),这个代价很大。此时的问题从水平如何拆分变成了,当增加或者删除节点时,对于大多数记录,保证原来分配到的某个节点,现在仍然应该分配到那个节点,将数据迁移量的降到最低,这就是一致性哈希要做的事情。在这里我们不指定是数据库还是什么,反正都是分布式存储节点。

    2.1 一致性哈希

    一致性 Hash 算法也是使用取模的思想,只是,刚才描述的取模法是对节点数量进行取模,而一致性 Hash 算法是对 2^32 取模,什么意思呢?简单来说,一致性 Hash 算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数 H 的值空间为 0-2^32-1(即哈希值是一个 32 位无符号整形),整个哈希环如下,从 0 ~ 2^32-1 代表的分别是一个个的节点,这个环也叫哈希环

    在这里插入图片描述

    然后我们将我们的节点进行一次哈希,按照一定的规则,比如按照 ip 地址的哈希值,让节点落在哈希环上。比如此时我们可能得到了如下图的环:

    在这里插入图片描述

    然后就是需要通过数据 key 找到对应的服务器然后存储了,我们约定,通过数据 key 的哈希值落在哈希环上的节点,如果命中了机器节点就落在这个机器上,否则落在顺时针直到碰到第一个机器。如下图所示 : A 的哈希值落在了 D2 节点的前面,往下找落在了 D2 机器上,D 的哈希值 在 D1 节点的前面,往下找到了 D1 机器,B 的哈希值刚好落在了 D1 节点上,依次~~~

    在这里插入图片描述

    2.2 一致性哈希的分析

    一致性哈希主要就是解决当机器减少或增加的时候,大面积的数据重新哈希的问题,主要从下面 2 个方向去考虑的,当节点宕机时,数据记录会被定位到下一个节点上,当新增节点的时候 ,相关区间内的数据记录就需要重新哈希。

    2.2.1 某节点宕机

    我们假设上图中的 节点 D2 因为一些原因宕机了,可以看到,只有数据 A 的记录需要重新重新定位存储到节点 D1 上,因为 D1 是 D2 的下一个节点,其它的数据都没有被影响到,此时被影响的仅仅是 图中的 D0-D2 这段区间的记录,也就是之前落在 D2 上的数据现在都要落到 D1 上面了。如下图

    在这里插入图片描述

    2.2.2 新增节点

    我们假设我们需要增加一台机器,也就是增加一个节点 D4,如下图所示,这个节点落在 D2-D1 之间,按照上述的哈希环上的哈希值落在节点的规则,那么此时之前落在 D2 到 D4 之间的数据都需要重新定位到新的节点上面了,而其它位置的数据是不需要有改变的。

    在这里插入图片描述

    2.3 一致性哈希的数据倾斜问题

    一致性 Hash 算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题。比如只有 2 台机器,这 2 台机器离的很近,那么顺时针第一个机器节点上将存在大量的数据,第二个机器节点上数据会很少。如下图所示,D0 机器承载了绝大多数的数据

    在这里插入图片描述

    2.4 虚拟节点解决数据倾斜问题

    为了避免出现数据倾斜问题,一致性 Hash 算法引入了虚拟节点的机制,也就是每个机器节点会进行多次哈希,最终每个机器节点在哈希环上会有多个虚拟节点存在,使用这种方式来大大削弱甚至避免数据倾斜问题。同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到 “D1#1”、“D1#2”、“D1#3” 三个虚拟节点的数据均定位到 D1 上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为 32 甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。这也是 Dubbo 负载均衡中有一种一致性哈希负载均衡的实现思想。

    在这里插入图片描述

    2.5 一致性哈希的应用案例

    一致性哈希用到的地方很多,特别是中间件里面,比如 Dubbo 的负载均衡也有一种策略是一致性哈希策略,使用的就是虚拟节点实现的。Redis 集群中也用到了相关思想但是没有用它而是根据实际情况改进了一下。而对于存储数据的节点水平切分的时候它的作用就更不可代替了。and so on・・・

    3. Redis 集群分槽的实现

    Redis 集群并没有直接使用一致性哈希,而是使用了哈希槽 (slot) 的概念,Redis 没有直接使用哈希算法 hash (),而是使用了 crc16 校验算法。槽位其实就是一个个的空间的单位。其实哈希槽的本质和一致性哈希算法非常相似,不同点就是对于哈希空间的定义。一致性哈希的空间是一个圆环,节点分布是基于圆环的,无法很好的控制数据分布,可能会产生数据倾斜问题。而 Redis 的槽位空间是自定义分配的,类似于 Windows 盘分区的概念。这种分区是可以自定义大小,自定义位置的。Redis 集群包含了 16384 个哈希槽,每个 Key 经过计算后会落在一个具体的槽位上,而槽位具体在哪个机器上是用户自己根据自己机器的情况配置的,机器硬盘小的可以分配少一点槽位,硬盘大的可以分配多一点。如果节点硬盘都差不多则可以平均分配。所以哈希槽这种概念很好地解决了一致性哈希的弊端。
    另外在容错性和扩展性上与一致性哈希一样,都是对受影响的数据进行转移而不影响其它的数据。而哈希槽本质上是对槽位的转移,把故障节点负责的槽位转移到其他正常的节点上。扩展节点也是一样,把其他节点上的槽位转移到新的节点上。

    需要注意的是,对于槽位的转移和分派,Redis 集群是不会自动进行的,而是需要人工配置的。所以 Redis 集群的高可用是依赖于节点的主从复制与主从间的自动故障转移。

    在这里插入图片描述***
    【Java 面试那点事】

    这里致力于分享 Java 面试路上的各种知识,无论是技术还是经验,你需要的这里都有!

    这里可以让你【快速了解 Java 相关知识】,并且【短时间在面试方面有跨越式提升】

    面试路上,你不孤单!
    在这里插入图片描述

    展开全文
  • 微服务系统中的数据一致性,你都会了吗

    万次阅读 多人点赞 2021-09-17 23:11:34
    你好,我是看山。 从单体架构到分布式架构,从巨石架构到微服务...需要注意一下,本文所设计的数据一致性,不是多数据副本之间保持数据一致性,而是系统之间的业务数据保持一致性。 本地事务 在早期的系统中,我们可.

    关于微服务系统中数据一致性的总结

    你好,我是看山。

    从单体架构到分布式架构,从巨石架构到微服务架构。系统之间的交互越来越复杂,系统间的数据交互量级也是指数级增长。作为一个系统,我们要保证逻辑的自洽和数据的自洽。

    数据自洽有两方面要求:

    1. 抛开代码,数据能够自己验证自己的准确性,也就是数据彼此之间不矛盾
    2. 所有数据准确且符合期望

    为了实现这两点,需要实现数据的一致性,为了实现一致性,就需要用到事务。

    需要注意一下,本文所设计的数据一致性,不是多数据副本之间保持数据一致性,而是系统之间的业务数据保持一致性。

    本地事务

    在早期的系统中,我们可以通过关系型数据库的事务保证数据的一致性。这种事务有四个基本要素:ACID。

    • A(Atomicity,原子性):整个事务中的所有操作,要么全部完成,要么全部失败,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
    • C(Consistency,一致性):一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。
    • I(Isolation,隔离性):隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。
    • D(Durability,持久性):在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

    这四个要素是关系型数据库的根本。无论系统多么复杂,只要使用同一个关系型数据库,我们就可以借助事务保证数据一致性。基于对关系型数据库的信任,我们可以认为本地事务是可靠的,开发过程中不需要额外的工作。从架构的角度,关系型数据库也是一个单独的系统,那关系型数据库与应用之间也是形成了分布式。所以我们先研究一下这种简单的分布式系统如何实现 ACID。

    首先,A(原子性)和 D(持久性)是彼此之间密不可分的两个属性:原子性保证了事务的所有操作,要么全部完成,要么全部失败,不可能停滞在中间某个环节;持久性保证了一旦事务完成,该事务对数据库所作的更改便持久的保存在数据库之中,不会因为任何原因而导致其修改的内容被撤销或丢失。

    众所周知,数据必须写入到磁盘后才能保证持久化,仅仅保存在内存中,一旦出现系统崩溃、主机断电等情况,数据就会丢失。所以,关键是“写入磁盘”要实现原子性和持久性,然而这个动作存在中间态:正在写入。所以,现代的关系型数据库通常采用追加日志记录的方式。将修改数据所需的全部信息(包括修改什么数据、数据物理上位于哪个内存页和磁盘块中、从什么值改成什么值,等等),以顺序追加的形式记录到磁盘中。只有在日志记录全部落盘,数据库在日志中看到代表事务成功提交的“提交记录”后,才会根据日志上的信息对真正的数据进行修改。修改完成后,再在日志中加入一条“结束记录”表示事务已完成持久化,这种事务实现方法被称为“提交日志”。

    本地事务

    我们能够通过日志保证一个事务的原子性和持久性,那如果出现多个事务访问同一个资源呢?作为程序猿都知道,多个线程/进程访问同一个资源,这个资源就称为临界资源,想要解决临界资源占用冲突的方式很简单,就是加锁。关系型数据库为我们准备了三种锁:

    • 写锁(Write Lock):同一个时刻,只有有一个事务对数据加写锁,所以写锁也被称为排它锁(exclusive Lock)。数据被加了写锁后,其他事务不能写入数据,也不能对其添加读锁(注意,是不能加读锁,但是可以读取数据)。
    • 读锁(Read Lock):同一时刻,多个事务可以对数据添加读锁,所以读锁也被称为共享锁(Shared Lock)。数据库被添加读锁后,数据不能被添加写锁。
    • 范围锁(Range Lock):对一个范围的数据添加写锁,这个范围的数据不能被写入。也可以算作写锁的批量行为。

    根据这三种锁的不同组合,我们可以实现四种不同的事务隔离级别:

    • 可串行化(Serializable):写入的时候加写锁,读取的时候加读锁,范围读写的时候加范围锁。
    • 可重复度(Repeatable Read):写入的时候加写锁,读取的时候加读锁,范围读写的时候不加锁,这样会出现读取相同范围数据的时候,返回结果不同,即幻读(Phantom Read)。
    • 读已提交(Read Committed):写入的时候加写锁,读取的时候加读锁,读取完成后立马释放读锁。这样会出现同一个事务多次读取相同数据,返回结果不同,即不可重复读(Non-Repeatable Read)。
    • 读未提交(Read Uncommitted):写入的时候加写锁,读取的时候不加锁。这样就会读取到另一个还未提交的事务写入的数据,即脏读(Dirty Read)。

    全局事务

    随着系统规模不断扩大,业务量不断增加。单体应用不再满足需求,我们会拆分系统,然后拆分数据库。此时,同一个请求中,就会出现同时访问多个数据库的情况。为了解决这种情况的数据一致性问题,X/Open 组织在 1991 年(那个时候我还小)提出了一套 X/Open XA 的处理事务的架构。XA 的核心内容是定义了全局的事务管理器(Transaction Manager,用于协调全局事务)和局部的资源管理器(Resource Manager,用于驱动本地事务)之间的通信接口,在一个事务管理器和多个资源管理器(Resource Manager)之间形成通信桥梁,通过协调多个数据源的一致动作,实现全局事务的统一提交或者统一回滚。与 XA 架构配套的是两阶段提交协议(2PC,Two Phase Commitment Protocol)。在这个协议中,最关键的点就是,多个数据库的活动,均由一个事务协调器的组件来控制。具体的分为 5 个步骤:

    1. 应用程序调用事务管理器中的提交方法
    2. 事务管理器将联络事务中涉及的每个数据库,并通知它们准备提交事务(这是第一阶段的开始)
    3. 接收到准备提交事务通知后,数据库必须确保能在被要求提交事务时提交事务,或在被要求回滚事务时回滚事务。如果数据库无法准备事务,它会以一个否定响应来回应事务管理器。
    4. 事务管理器收集来自各数据库的所有响应。
    5. 在第二阶段,事务管理器将事务的结果通知给每个数据库。如果任一数据库做出否定响应,则事务管理器会将一个回滚命令发送给事务中涉及的所有数据库。如果数据库都做出肯定响应,则事务管理器会指示所有的资源管理器提交事务。一旦通知数据库提交,此后的事务就不能失败了。通过以肯定的方式响应第一阶段,每个资源管理器均已确保,如果以后通知它提交事务,则事务不会失败。

    2PC

    两阶段提交协议实现简单,但存在几个明显缺陷:

    • 单点问题:事务管理器在两段提交中具有举足轻重的作用,事务管理器等待资源管理器回复时可以有超时机制,允许资源管理器宕机,但资源管理器等待事务管理器指令时无法做超时处理。一旦宕机的不是其中某个资源管理器,而是事务管理器的话,所有资源管理器都会受到影响。如果事务管理器一直没有恢复,没有正常发送 Commit 或者 Rollback 的指令,那所有资源管理器都必须一直等待。
    • 性能问题:两段提交过程中,所有资源管理器相当于被绑定成为一个统一调度的整体,期间要经过两次远程服务调用,三次数据持久化(准备阶段写重做日志,事务管理器做状态持久化,提交阶段在日志写入 Commit Record),整个过程将持续到资源管理器集群中最慢的那一个处理操作结束为止,这决定了两段式提交的性能通常都较差。
    • 一致性风险:尽管提交阶段时间很短,但这仍是一段明确存在的危险期。如果事务管理器在发出准备指令后,根据收到各个资源管理器发回的信息确定事务状态是可以提交的,事务管理器会先持久化事务状态,并提交自己的事务,如果这时候网络断开,无法再通过网络向所有资源管理器发出 Commit 指令的话,就会导致部分数据(事务管理器的)已提交,但部分数据(资源管理器的)既未提交,也没有办法回滚,产生了数据不一致的问题。

    能够发现问题,就能够想到办法解决。我们高中老师说了,只要意识不滑坡,办法总比困难多。所以又发展出了三阶段提交协议(3PC,Three Phase Commitment Protocol),能够缓解单点问题和准备阶段的性能问题。这个协议把 2PC 中的准备阶段拆分为 CanCommit 和 PreCommit,把提交阶段改名为 DoCommit。CanCommit 是询问阶段,让每个资源管理器根据自身情况判断该事务是否有可能完成。

    3PC 本质是通过一次问询,如果大家都说自己可以,那成事的可能性很大,减少了准备阶段直接锁定资源的重操作。由于事务失败回滚概率变小的原因,在三段式提交中,如果在 PreCommit 阶段之后发生了事务管理器宕机,即资源管理器没有能等到 DoCommit 的消息的话,默认的操作策略将是提交事务而不是回滚事务或者持续等待,这就相当于避免了事务管理器单点问题的风险。

    3PC

    分布式事务

    说到分布式事务,不得不提 CAP 理论:任何分布式系统只可同时满足一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)中的两点,没法三者兼顾。

    CAP 理论

    • 一致性(Consistency):数据在任何时刻、任何分布式节点中所看到的都是符合预期的。
    • 可用性(Availability):系统不间断地提供服务的能力,可用性是由可靠性(Reliability)和可维护性(Serviceability)计算得出的比例值。可靠性通过平均无故障时间(Mean Time Between Failure,MTBF)来度量;可维护性通过平均可修复时间(Mean Time To Repair,MTTR)来度量。可用性衡量系统可以正常使用的时间与总时间之比,公式为:A=MTBF/(MTBF+MTTR)。
    • 分区容错性(Partition Tolerance):分布式环境中部分节点因网络原因而彼此失联后,系统仍能正确地提供服务的能力。

    CAP 理论定义是经过几次修改的,修改后的定义本质没有区别,只是在逻辑上更加严谨。本文为了好理解,使用了最容易让大众接收并理解的定义。

    既然 CAP 不能兼顾,那我们来看看缺少其中一环会出现什么情况:

    • 选择 CA 放弃 P:即我们认为网络可靠不会出现分区情况,这种可靠是各个节点之间不会出现网络延迟、中断等情况,显然是不成立的。
    • 选择 CP 放弃 A:这样做就是抛弃了可用性,为了保证数据一致性,一旦出现网络异常,节点之间的信息同步时间可以无限制地延长。使用 CP 组合的一般用于对数据质量要求很高的场合,也就是为了保证数据完全一致,暂时不提供服务,直到网络完全恢复,这可能持续一个不确定的时间,尤其是在系统已经表现出高延迟时或者网络故障导致失去连接时。
    • 选择 AP 放弃 C:意味着一旦发生网络分区,优先提供服务可用,放弃数据一致性。这是目前分布式系统的主流选择,因为网络本身就是链接不同区域的服务器的,网络又是不可靠的,所以 P 不能被舍弃。同时,我们实现分布式系统就是为了提高可用性,这是我们的目的,不能舍弃。

    这里需要再说明一下,我们选择 AP 放弃 C 不是放弃数据一致,而是暂时放弃强一致性(Strong Consistency),而是选择弱一致性,即最终一致性(Eventual Consistency):系统中的所有数据副本经过一段时间后,最终能够达到一致的状态。这里所说的一段时间,也要是用户可接受范围内的一段时间。

    最终一致性也有一个理论支撑:BASE 理论(不得不说,理论界的缩写真牛啊,ACID 是酸,CAP 是帽子,BASE 是碱),内容主要包括:

    • 基本可用(Basically Available):当系统在出现不可预知故障的时候,允许损失部分可用性。比如,允许响应时间增长,允许部分非关键接口降级或熔断等。
    • 软状态(Soft State):软状态也称为弱状态,和硬状态相对。是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。
    • 最终一致性(Eventually Consistent):最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。

    在工程实践中,最终一致性分为 5 种,这 5 种方式会结合使用,共同实现最终一致性:

    • 因果一致性(Causal consistency):如果节点 A 在更新完某个数据后通知了节点 B,那么节点 B 之后对该数据的访问和修改都是基于 A 更新后的值。于此同时,和节点 A 无因果关系的节点 C 的数据访问则没有这样的限制。
    • 读己之所写(Read your writes):节点 A 更新一个数据后,它自身总是能访问到自身更新过的最新值,而不会看到旧值。
    • 会话一致性(Session consistency):会话一致性将对系统数据的访问过程框定在了一个会话当中,系统能保证在同一个有效的会话中实现“读己之所写”的一致性,也就是说,执行更新操作之后,客户端能够在同一个会话中始终读取到该数据项的最新值。
    • 单调读一致性(Monotonic read consistency):如果一个节点从系统中读取出一个数据项的某个值后,那么系统对于该节点后续的任何数据访问都不应该返回更旧的值。
    • 单调写一致性(Monotonic write consistency):一个系统要能够保证来自同一个节点的写操作被顺序的执行。

    一致性关系模型

    有了理论之后,我们来说一下实现最终一致性的几种模式。

    可靠事件模式

    可靠事件模式属于事件驱动架构:当某个事件发生时,例如更新一个业务实体,服务会向消息代理发布一个事件。消息代理会向订阅事件的服务推送事件,当订阅这些事件的服务接收此事件时,就可以完成自己的业务,也可能会引发更多的事件发布。

    我们通过一个例子来解释一下这种模式,用户下单成功后,订单系统需要通知库存系统减库存。

    可靠事件模式

    1. 订单系统根据用户操作完成下单操作。此时会使用同一个本地事务保存订单信息和写入事件。
    2. 另外一个消息服务会轮询事件表,将状态是“进行中”的事件以消息形式发送到消息服务中。如果发送失败,因为是轮询任务,会在下一次轮询的时候再次发送。(此处有一些优化点,本例为了简化模型,不展开)
    3. 消息服务向订阅下单消息的库存服务发送下单成功消息,库存服务开始处理。此时会有这么集中情况:
      1. 库存服务扣减库存成功,消息服务接收到处理成功响应。消息服务将响应结果返回给订单服务,订单服务中事件接收器将事件修改为“已完成”。
      2. 库存服务扣减库存失败,消息服务接收到处理失败响应。此时消息服务会再次向库存服务发送消息,直到得到成功响应。如果失败次数达到阈值,可以告警通知人工介入。
      3. 消息服务给订单服务返回结果时,发生失败,订单服务没有接收到成功响应。这个时候,事件轮询逻辑会再次将事件发送给消息服务。这样,库存服务会重复收到扣减库存的消息,所以要求库存服务做好幂等。库存服务发现消息已经处理过,直接返回成功。

    这种靠着持续重试来保证可靠性的解决方案,叫做“最大努力交付”(Best-Effort Delivery),也是“可靠”两个字的来源。

    可靠事件模式还有一种更普通的形式,被称为“最大努力一次提交”(Best-Effort 1PC),指的就是将最有可能出错或最核心的业务以本地事务的方式完成后,采用不断重试的方式(不限于消息服务)来促使同一个分布式事务中的其他关联业务全部完成。找到最可能出错的方式是提前做好出错概率的先验评估,才能够知道哪块最容易出错。找到最核心的业务的方式是找到那种只要成功,其他业务必须成功的那块业务。

    这里我们再补充两个概念:

    • 业务异常:业务逻辑产生错误的情况,比如账户余额不足、商品库存不足等。
    • 技术异常:非业务逻辑产生的异常,如网络连接异常、网络超时等。

    TCC 模式

    TCC(Try-Confirm-Cancel)是一种业务侵入式较强的事务方案,要求业务处理过程必须拆分为“预留业务资源”和“确认/释放消费资源”两个子过程,由统一的服务协调调度不同业务系统的子过程。分为以下三个阶段:

    • Try:尝试执行阶段,完成所有业务可执行性的检查(保障一致性),并且预留好全部需要用到的业务资源(保障隔离性)。
    • Confirm:确认执行阶段,不进行任何业务检查,直接使用 Try 阶段准备的资源来完成业务处理。Confirm 阶段可能会重复执行,需要满足幂等性。
    • Cancel:取消执行阶段,释放 Try 阶段预留的业务资源。Cancel 阶段可能会重复执行,需要满足幂等性。

    TCC 模式

    1. 订单系统创建事务,生成事务 ID(用于作为识别请求幂等的标识),通过活动管理器记录活动日志。
    2. 进入 Try 阶段
      1. 调用账户系统,检查账户余额是否充足,如果充足,冻结需要的金额,此时账户余额是临界资源,需要通过排它锁或乐观锁保证冻结操作的安全性。
      2. 调用库存系统,检查商品库存是否充足,如果充足,锁定需要的库存,锁库操作也需要加锁保证安全
    3. 如果所有业务返回成功,记录活动日志为 Confirm,进入 Confirm 阶段:
      1. 调用账户系统,扣减冻结的金额
      2. 调用库存系统,扣减锁定的库存
    4. 第 3 步操作中如果全部完成,事务宣告结束。如果第 3 步中任何一方出现异常,都会根据活动日志中的记录,重复执行 Confirm 操作,即进行最大努力交付。所以各业务系统的 Confirm 操作需要实现幂等性。
    5. 如果第 2 步有任何一方失败(包括业务异常和技术异常),将活动日志记录为 Cancel,进入 Cancel 阶段:
      1. 调用账户系统,释放冻结的金额
      2. 调用库存系统,释放锁定的库存
    6. 第 5 步操作中如果全部完成,事务宣告失败。如果第 5 步中任何一方出现异常(包括业务异常和技术异常),都会根据活动日志中的记录,重复执行 Cacel 操作,即最大努力交付。所以各业务系统的 Cancel 操作也需要实现幂等性。

    是不是感觉 TCC 与 2PC 的很像,两者的区别在于,TCC 位于业务代码层面,属于白盒,2PC 位于基础设施层面,属于黑盒。所以 TCC 有更高的灵活性,可以根据需要,调整资源锁定的粒度。

    TCC 在业务执行过程中可以预留资源,解决了可靠事件模式的资源隔离问题。但是,TCC 还有两个明显缺点:

    1. TCC 将基础设施层的逻辑上移到业务代码,对业务有很高的侵入性,需要更高的开发成本,开发成本提升,相对应的维护成本、开发人员的素质等,都会有更高的要求。
    2. TCC 要求资源可以锁定、占用或释放,但是有的资源属于外部系统,没有办法实现锁定。

    鉴于上面的两个缺点,我们看看 SAGA 是否可以弥补。

    SAGA 模式

    SAGA 在英文中是“长篇故事、长篇记叙、一长串事件”的意思。SAGA 模式的提出远早于分布式事务概念的提出(再次对前辈大佬佩服的五体投地),它源于 1987 年普林斯顿大学的 Hector Garcia-Molina 和 Kenneth Salem 在 ACM 发表的一篇论文《SAGAS》。文中提出了一种提升“长时间事务”(Long Lived Transaction)运作效率的方法,大致思路是把一个大事务分解为可以交错运行的一系列子事务集合,后来发展成将一个分布式环境中的大事务分解为一系列本地事务的设计模式。在有的文章中,将这种模式称为业务补偿模式,SAGA 是对事务形式的描述,业务补偿是对事务行为的描述,其本质是一样的。

    SAGA 模式有两种实现:

    • 正向恢复(Forward Recovery):顺序执行各个子事务,如果遇到某个子事务执行失败,将一直重试该操作,知道成功,然后继续执行下一个子事务。比如用户下单支付成功了,就一定要扣减库存。
    • 反向恢复(Backward Recovery):顺序执行各个子事务,如果遇到某个子事务执行失败,将执行该子事务的补偿操作(避免因为技术异常造成的失败,补偿操作需要幂等),然后倒序执行已经成功的子事务的补偿操作。这种一般是可取消的批量操作,比如出行订票,需要购买飞机票、订酒店、买门票,如果买门票失败了,飞机票和酒店就可以取消了。

    SAGA 模式

    根据这两种实现,SAGA 可以分为两部分:

    • 子事务(Normal Transactions):大事务拆分若干个小事务,将整个事务 T 分解为 n 个子事务,命名为 T1、T2、…、Tn。每个子事务都应该是或者能被视为是原子行为。如果分布式事务能够正常提交,其对数据的影响(最终一致性)应与连续按顺序成功提交 Ti 等价。
    • 补偿事务(Compensating Transactions):每个子事务对应的补偿动作,命名为 C1、C2、…、Cn

    子事务与补偿动作需要满足一些条件:

    1. Ti与 Ci必须对应
    2. 补偿动作 Ci一定会执行成功,即需要实现最大努力交付。
    3. Ti与 Ci需要具备幂等性

    文末总结

    本文主要总结了本地事务、全局事务、最终一致性等方式实现数据自洽。重点介绍了实现最终一致性的集中模式:可靠事件模式、TCC 模式、SAGA 模式等。数据的一致性一直是个难题,随着微服务化之后,数据一致性更加困难,有困难不怕,只要不放弃,总会解决的。

    参考


    你好,我是看山。游于码界,戏享人生。如果文章对您有帮助,请点赞、收藏、关注。我还整理了一些精品学习资料,关注公众号「看山的小屋」,回复“资料”即可获得。

    个人主页:https://www.howardliu.cn
    个人博文:关于微服务系统中数据一致性的总结
    CSDN 主页:https://kanshan.blog.csdn.net/
    CSDN 博文:关于微服务系统中数据一致性的总结

    公众号:看山的小屋

    展开全文
  • 串联的矩阵的维度不一致

    千次阅读 2021-04-23 10:59:06
    找了个潮流计算的程序,按照程序里的例子输入却说串联的矩阵的维度不一致。错误在最后,可以拉到最后看。能不能帮忙看看是什么地方出错,谢谢啦!>> %简单潮流计算的牛顿拉夫逊程序,相关的原始数据数据数据...
  • redirect_uri域名与后台配置不一致

    万次阅读 2021-10-24 15:53:12
    访问公众号网页提示: redirect_uri域名与后台配置不一致 这个错误相信每个开发公众号的开发者都遇到过,本文记录详细配置步骤 在工作中也有很多客户问我这个问题,也是为了避免重复沟通,到时候把这篇文章发给客户就...
  • 串联的矩阵维度不一致怎么解决

    千次阅读 2021-04-18 03:48:55
    我的代码是A,B两个矩阵都是24*24的矩阵,对数据进行了归一化处理,但是运行老是显示串联的矩阵不一致。代码如下SPREAD=21.8;A=[3.9 4.1 3 3 2.8 2.3 2.9 3.3 3.5 4.1 4.5 5.25.1 6 6.8 7.1 6.5 4 4.9 6.6 8.7 6.2 7 ...
  • 浅析数据一致

    万次阅读 多人点赞 2016-02-19 15:27:38
    什么是数据一致性?  在数据有多分副本的情况下,如果网络、服务器或者软件出现故障,会导致部分副本写入成功,部分副本写入失败。这就造成各个副本之间的数据不一致,数据内容冲突。 实践中,导致数据不一致的情况...
  • i++和++i是什么意思 i++和++i的区别

    千次阅读 2021-03-17 20:25:04
    把i++的运算过程拆分开,等效于i=i+1可以看到运算结果是一致的。x = i ++; //先让x变成i的值1,再让i加12、++i是前缀递增的意思,++i是先进行自增或者自减运算,再进行表达式运算。运算结果可以发现,...
  • 要串联的数组的维度不一致

    千次阅读 2021-04-22 18:26:59
    clcclearfor i=1:5fileName = [num2str(i,'%04d') '.txt']; %读取瞬时流速a=load(fileName);a(1:80,3)=0;a(:,6)=-a(:,6);E=[];for j=1:238for k=((j-1)*79+j):1:(j*79+(j-1))B=(a(k+1,5)-a(k,5))/0.07678;...
  • 如何保证缓存与数据库双写时的数据一致性?在做系统优化时,想到了将数据进行分级存储的思路。因为在系统中会存在一些数据,有些数据的实时性要求不高,比如一些配置信息。基本上配置了很久才会变一次。而有一些数据...
  • 域名与后台配置不一致 这通常发生在获取网页授权,请求https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=...
  • MATLAB错误记录:错误使用 cat 串联的矩阵的维度不一致今天想用matlab读取一个数据文件。用importdata读入后照例储存成了cell类型。但当我想用cell2mat将其转化为矩阵时却出现了这个问题:错误使用 cat 串联的矩阵的...
  • 1.把txt下载文件放置在...代码里url和网页授权一致。直接写consturl= 'https://gzh.sunyard.com.cn/#/login/login' 。测试就会出现10003 最终问题是:微信url配置的问题。 解决办法:redirect_uri 要使用ur...
  • json字段名不一致的问题

    千次阅读 2019-06-21 16:54:29
    项目开发过程中,有时候可能要对接第三方平台,可能就会存在字段名不一样的问题,而双方的字段名不一致, 而代码开发已经有一段时间勒,如果就因为字段名不一样的问题,双方改成属性名一致,这样改动量太大,也不...
  • 一致性hash和普通hash区别?

    千次阅读 2020-07-29 15:31:22
    碰撞(冲突):如果两个关键字通过hash函数得到的值是一样的,就是碰撞或冲突。 Hash表(散列表):根据散列函数和冲突处理将一组关键字分配在连续的地址空间内,并以散列值记录在表中的存储位置,这种表成为散列表...
  • 它是指几个投标人之间相互约定,一致抬高或压低投标报价进行投标,通过限制竞争,排挤其他投标人,使某个利益相关者中标,从而谋取利益的手段和行为。 不同投标人的投标文件由同一单位或个人编制的可视为投标人...
  • 手机ram是什么ram是什么意思?RAM即大家常说的运行内存,简称运存,是一种在手机中用来暂时保存数据的元件,相当于电脑中的内存条。它可以随时读写,而且速度很快,通常作为作业系统或其他正在运行中的程式之临时...
  • 总线矩阵:业务过程和维度的交点; 一致性维度:同一集市的维度表,内容相同或包含; 一致性事实:不同集市的同一事实,需保证口径一致,单位统一。
  • 一般出这个错误,解决办法是确保微信公众平台里的网页授权域名填写一致即可。 但是今天碰到另一个坑,就是官方的支付demo里的调用接口网址写的是http 就是WxPay.JsApiPay.php里的 GetOpenid函数里 public ...
  • 1.处理之前,先保证裁剪的栅格数据和裁剪范围的栅格数据的投影必须一样,否则无法保持一致。 2.选择mask工具,设置好输入和输出后,点击下面的环境设置 3.点开处理范围(Processing Extent),点开范围(Extent)和...
  • 下面通过几个问题来说明kafka如何来保证消息可靠性与一致性 在kafka中ISR是什么? 在zk中会保存AR(Assigned Replicas)列表,其中包含了分区所有的副本,其中 AR = ISR+OSR ISR(in sync replica):是kafka动态...
  • 提示错误为:更新包与已安装应用的签名不一致 出现包签名不一致的问题,说明原有的安装包并没有卸载干净。然而,在应用中并没有看到相应的软件。然后去文件夹中查找相应的包,并删除。发现仍然存在这个问题。 解决...
  • C语言中的input是什么意思

    万次阅读 2021-05-19 10:36:39
    这应该是用户自定的函数,input在英语里面是输入的意思。2、C语言中一般输入使用的函数是scanf。scanf与printf函数一样,都被定义在头文件stdio.h里,因此在使用scanf函数时要加上#include 。它是格式输入函数,即按...
  • 一致性可以理解为在任意时刻,所有节点中的数据是一样的。同一时间点,你在节点A中获取到key1的值与在节点B中获取到key1的值应该都是一样的。 弱一致性包含很多种不同的实现,目前分布式系统中广泛实现的是最终...
  • 差点意思 了。 redis 的线程模型了解么? Redis 内部使用文件事件处理器 file event handler ,这个文件事件处理器是单线程的,所以 Redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听多个 ...
  • 华为手机提示更新包与已安装应用的签名不一致

    万次阅读 多人点赞 2019-08-16 20:20:54
    华为手机提示更新包与已安装应用的签名不一致自己尝试解决网上寻找解决方案1、配置adb2、查看APK的包名3、彻底卸载原有应用信息新的思考 最近使用华为手机(HUAWEI Mate 20)调试程序,发现一个问题。直接使用Android...
  • 答案是有可能可以。 如果可以隐式转化,那就是可以,int和long是可以隐式转换的,但...指针的话,最好一致 注意 const形参通常可以用非const 反之一般不可以 看一下数据类型隐式转化规则你就知道能不能转换了。 ...
  • redirect_uri和后台配置明明是一致的,但就一直报这个错,大佬们有谁知道问题吗 ``` ... ...
  • 背景: 解决办法: 1、检查项目中的APPID和微信公众号后台的是否一致 2、检查是否在微信公众号后台添加了网页授权域名

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 270,338
精华内容 108,135
关键字:

一致是一样的意思吗