Nginx做负载均衡,调度是使用ip_hash 我用不同机器每次都登陆的是同一个服务器请问是什么问题

Nginx做负载均衡,调度是使用ip_hash 我用不同机器每次都登陆的是同一个服务器请问是什么问题,第1张

这个是很正常的,ip_hash的负载均衡是以客户端的ip地址作为hash错作的key进而计算hash值得。这种策略能保证一个ip访问到的永远是同一台机器。
(1)但是有一种情况就是多个ip的hash值是相同的,在这种情况下,这几个不同的ip访问到的就是同一台机器了。
(2)还有一种情况就是,虽然你每次用不同的机器,但是这些机器都是通过一个相同的出口ip来访问服务器,这时,你访问到的也永远是一台服务器。

这是正常的。IP_hash主要作用就是让同一个IP连接到后台固定的一台机器。除非,这台机器停止响应,或者挂掉,或者被Nginx踢除。
这有助于Session保持。
如果你想轮询的话,就不要加Session。这样客户端访问看看。就会变化。

个人对数据安全理解是:
算法是公开的,在当前世界算力下,理论上不可破解的,是靠秘钥来保证安全的,不是算法本身。

在我们日常的开发过程中,我们开发人员保证数据安全,主要通过四个手段。

通过对数据的签名(其实就是对数据进行HASH)保证传输过程中数据不被篡改。
如:微信的 “微信公众平台的接入” 的数据签名(signature),保证消息的确来自微信服务器,并没有被篡改过。

通过数据进行对称加密(主要是AES),保证数据传输过程中数据不被泄密。
如:微信的 “微信公众平台的接入” 的数据加密传输。

通过非对称加密(RSA)的公钥对数据进行加密,然后通过私钥对应的私钥对数据进行解密,也是保证数据传输过程中数据不被泄密,非对称加密的速度比较慢。
如:>

环割法(一致性 hash)环割法的原理如下:

1 初始化的时候生成分片数量 X × 环割数量 N 的固定方式编号的字符串,例如 SHARD-1-NODE-1,并计算所有 X×N 个字符串的所有 hash 值。

2 将所有计算出来的 hash 值放到一个排序的 Map 中,并将其中的所有元素进行排序。

3 输入字符串的时候计算输入字符串的 hash 值,查看 hash 值介于哪两个元素之间,取小于 hash 值的那个元素对应的分片为数据的分片。

跳跃法(jumpstringhash)跳跃法的原理如下:1 根据公式:

将数据落在每一个节点的概率进行平均分配。

2 对于输入的字符串进行计算 hash 值,通过判断每次产生的伪随机值是否小于当前判定的节点 1/x,最终取捕获节点编号最大的作为数据的落点。3 在实际使用中使用倒数的方法从最大节点值进行反向判断,一旦当产生的伪随机值大于 x 则判定此节点 x 作为数据的落点。

数据比较

下面将通过测试对环割法和跳跃法的性能及均衡性进行对比,说明 DBLE 为何使用跳跃法代替了环割法。

数据源:现场数据 350595 条

测试经过:

1 通过各自的测试方法执行对于测试数据的分片任务。

2 测试方法:记录分片结果的方差;记录从开始分片至分片结束的时间;记录分片结果与平均数的最大差值。

3 由于在求模法 PartitionByString 的方法中要求分片的数量是 1024 的因数,所以测试过程只能使用 2 的指数形式进行测试,并在 PartitionByString 方法进行测试的时候不对于 MAC 地址进行截断,取全量长度进行测试。

1、首先把每一个存储块,通过MD5计算其值。
2、其次传递MD5值到服务器。
3、最后让服务器比对MD5来确定有没有被修改,如若MD5值不相等,则判定这个文件块有被修改过。

通俗来讲,哈希值就是文件的身份z,不过比身份z还严格。他是根据文件大小,时间,类型,创作者,机器等计算出来的,很容易就会发生变化,谁也不能预料下一个号码是多少,也没有更改他的软件。哈希算法将任意长度的二进制值映射为固定长度的较小二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明文而且哪怕只更改该段落的一个字母,随后的哈希都将产生不同的值。要找到散列为同一个值的两个不同的输入,在计算上是不可能的。

有这样一种情境,有三万张我们要均匀放置于三个缓存服务器上
简单的做法是对缓存的key进行哈希计算,得到的值进行取模计算,所得到的余数,便是缓存的服务器编号

hash % 机器数 = 余数
当机器数为3时无论值为多少,其余数永远只有0,1,2三种情况
那么根据余数,我们给服务器进行编号s0,s1,s2,余数为0的放置于s0服务器上,1,2同理。

这样我们就将三万张的缓存均分成三份存放与三台缓存服务器中
因为对同一张进行哈希计算时,所得到的哈希值是不变的,所以当需要访问时,只要再次进行哈希计算和取模计算,就能获取到存放于哪台服务器,便可以去该服务器中查找满足了我们的需求。而这种算法也称之为哈希算法

这其中有一个问题,那便是如果我增加一台服务器呢
可以预见的是,当增加一台服务器服务器数变成了4而余数也出现了4种情况

这时向s2的服务器查询时,无法读取到,这导致了程序无法从缓存服务器中读取数据,这时程序就会向后端服务器请求,而大量的缓存同时失效,会导致所有请求都指向后端服务器,这会引起后端服务器的崩溃。
这是就要引入一致性哈希算法

还是同样的三个缓存服务器,这次我们将哈希值对2 32取模,所得到的数一定是1到2 32之间的一个整数
然后我们想像一个圆环,其上的每一个点都代表1到2^32之间的一个整数,而这个圆环也被称为hash环
之后我们对服务器A进行取模计算,这样算出来的整数肯定在1到2^32之间,将这个整数代表为服务器A,并且我们可以将这个整数映射到哈希环上,同样的道理我们处理另外两个服务器,这时三个服务器都被映射到了哈希环上,对于我们也将他映射到哈希环上
那么我们只要从的哈希值开始,沿顺时针在哈希环上查找,遇到的第一个服务器便是缓存所在的服务器
这时哪怕新添加一个服务器在哈希环上,我门所丢失的缓存数据也只是新添加的服务器到逆时针方向遇到的第一个服务器这部分数据,而这样仍然有大部分缓存在缓存服务器中可以被查找到,这样可以帮助后端服务器分担大部分压力,不会使服务器崩溃,而这部分丢失的缓存数据,之后重新在后端加载便可以了

这又引入了另一个问题,哈希偏斜
我们无法确保三个服务器在哈希环上为均分的状态,很有可能其中一台服务器分到了很大部分而另两台分到了很少的部分,这样同样会有后端服务器崩溃的隐患
我们可以添加很多虚拟结点同一个服务器我们分出许多虚拟节点,映射在哈希环上,哈希环上的节点越多,缓存被均分的概率便越大,这样可以尽可能的保证缓存在服务器上是接近理想均分的状态,避免了哈希偏斜的问题

随着时间和业务的发展,数据库中的数据量增长是不可控的,库和表中的数据会越来越大,随之带来的是更高的 磁盘 IO 系统开销 ,甚至 性能 上的瓶颈,而单台服务器的 资源终究是有限 的。

因此在面对业务扩张过程中,应用程序对数据库系统的 健壮性 安全性 扩展性 提出了更高的要求。

以下,我从数据库架构、选型与落地来让大家入门。

数据库会面临什么样的挑战呢?

业务刚开始我们只用单机数据库就够了,但随着业务增长,数据规模和用户规模上升,这个时候数据库会面临IO瓶颈、存储瓶颈、可用性、安全性问题。

为了解决上述的各种问题,数据库衍生了出不同的架构来解决不同的场景需求。

将数据库的写 *** 作和读 *** 作分离,主库接收写请求,使用多个从库副本负责读请求,从库和主库同步更新数据保持数据一致性,从库可以水平扩展,用于面对读请求的增加。

这个模式也就是常说的读写分离,针对的是小规模数据,而且存在大量读 *** 作的场景。

因为主从的数据是相同的,一旦主库宕机的时候,从库可以 切换为主库提供写入 ,所以这个架构也可以提高数据库系统的 安全性 可用性

优点:

缺点:

在数据库遇到 IO瓶颈 过程中,如果IO集中在某一块的业务中,这个时候可以考虑的就是垂直分库,将热点业务拆分出去,避免由 热点业务 密集IO请求 影响了其他正常业务,所以垂直分库也叫 业务分库

优点:

缺点:

在数据库遇到存储瓶颈的时候,由于数据量过大造成索引性能下降。

这个时候可以考虑将数据做水平拆分,针对数据量巨大的单张表,按照某种规则,切分到多张表里面去。

但是这些表还是在同一个库中,所以库级别的数据库 *** 作还是有IO瓶颈(单个服务器的IO有上限)。

所以水平分表主要还是针对 数据量较大 ,整体业务 请求量较低 的场景。

优点:

缺点:

四、分库分表

在数据库遇到存储瓶颈和IO瓶颈的时候,数据量过大造成索引性能下降,加上同一时间需要处理大规模的业务请求,这个时候单库的IO上限会限制处理效率。

所以需要将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。

分库分表能够有效地缓解单机和单库的 性能瓶颈和压力 ,突破IO、连接数、硬件资源等的瓶颈。

优点:

缺点:

注:分库还是分表核心关键是有没有IO瓶颈

分片方式都有什么呢?

RANGE(范围分片)

将业务表中的某个 关键字段排序 后,按照顺序从0到10000一个表,10001到20000一个表。最常见的就是 按照时间切分 (月表、年表)。

比如将6个月前,甚至一年前的数据切出去放到另外的一张表,因为随着时间流逝,这些表的数据被查询的概率变小,银行的交易记录多数是采用这种方式。

优点:

缺点:

HASH(哈希分片)

将订单作为主表,然后将其相关的业务表作为附表,取用户id然后 hash取模 ,分配到不同的数据表或者数据库上。

优点:

缺点:

讲到这里,我们已经知道数据库有哪些架构,解决的是哪些问题,因此, 我们在日常设计中需要根据数据的特点,数据的倾向性,数据的安全性等来选择不同的架构

那么,我们应该如何选择数据库架构呢?

虽然把上面的架构全部组合在一起可以形成一个强大的高可用,高负载的数据库系统,但是架构选择合适才是最重要的。

混合架构虽然能够解决所有的场景的问题,但是也会面临更多的挑战,你以为的完美架构,背后其实有着更多的坑。

1、对事务支持

分库分表后(无论是垂直还是水平拆分),就成了分布式事务了,如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价(XA事务);如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担(TCC、SAGA)。

2、多库结果集合并 (group by,order by)

由于数据分布于不同的数据库中,无法直接对其做分页、分组、排序等 *** 作,一般应对这种多库结果集合并的查询业务都需要采用数据清洗、同步等其他手段处理(TIDB、KUDU等)。

3、数据延迟

主从架构下的多副本机制和水平分库后的聚合库都会存在主数据和副本数据之间的延迟问题。

4、跨库join

分库分表后表之间的关联 *** 作将受到限制,我们无法join位于不同分库的表(垂直),也无法join分表粒度不同的表(水平), 结果原本一次查询就能够完成的业务,可能需要多次查询才能完成。

5、分片扩容

水平分片之后,一旦需要做扩容时。需要将对应的数据做一次迁移,成本代价都极高的。

6、ID生成

分库分表后由于数据库独立,原有的基于数据库自增ID将无法再使用,这个时候需要采用其他外部的ID生成方案。

一、应用层依赖类(JDBC)

这类分库分表中间件的特点就是和应用强耦合,需要应用显示依赖相应的jar包(以Java为例),比如知名的TDDL、当当开源的 sharding-jdbc 、蘑菇街的TSharding等。

此类中间件的基本思路就是重新实现JDBC的API,通过重新实现 DataSource PrepareStatement 等 *** 作数据库的接口,让应用层在 基本 不改变业务代码的情况下透明地实现分库分表的能力。

中间件给上层应用提供熟悉的JDBC API,内部通过 sql解析 sql重写 sql路由 等一系列的准备工作获取真正可执行的sql,然后底层再按照传统的方法(比如数据库连接池)获取物理连接来执行sql,最后把数据 结果合并 处理成ResultSet返回给应用层。

优点

缺点

二、中间层代理类(Proxy)

这类分库分表中间件的核心原理是在应用和数据库的连接之间搭起一个 代理层 ,上层应用以 标准的MySQL协议 来连接代理层,然后代理层负责 转发请求 到底层的MySQL物理实例,这种方式对应用只有一个要求,就是只要用MySQL协议来通信即可。

所以用MySQL Navicat这种纯的客户端都可以直接连接你的分布式数据库,自然也天然 支持所有的编程语言

在技术实现上除了和应用层依赖类中间件基本相似外,代理类的分库分表产品必须实现标准的MySQL协议,某种意义上讲数据库代理层转发的就是MySQL协议请求,就像Nginx转发的是>

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zz/13463920.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-08-12
下一篇 2023-08-12

发表评论

登录后才能评论

评论列表(0条)

保存