分布式_总笔记

----------------------------------总结-------------------------------------------

1. 分布式基础知识点:

(1)一致性哈希和哈希取模算法的区别:

哈希取模算法:即hash(服务器A的IP地址) % 服务器的数量,常用在nginx的IP哈希取模算法,数据库的分库分表策略里;

一致性哈希:即hash(服务器A的IP地址) % 2^32,可以想象成一个圆了,常用在服务层dubbo负载均衡算法、缓存分片算法

注:http://www.zsythink.net/archives/1182

(2)一致性哈希:jedis采用一致性哈希算法路由redis服务器的流程是

a. 求出redis服务器的哈希值,将其配置到0-2^32的圆上;

b. 采用相同方法求出待存储的Key的哈希值,并映射到相同的圆上;

c. 从数据映射到的位置开始顺时针查找,找到的第一台服务器就是数据保存的位置;

d. 如果顺时针寻找过程中超过2^32仍然找不到节点,则保存到最开始的第一台服务器上;

(4)架构演进过程:

单体应用架构SSH -> 垂直应用架构(RESTful) -> SOA(Dubbo) -> 微服务(SpringCloud)

RPC:即让调用远程服务和调用本地服务一样,底层是基于socket进行通信;

(5)区别:双机热备(一主一备)、双机互备(互为主备)、双机双工(集群)

双机热备:主+备=一套业务跑在两套机器上(配置最好一样),两机用心跳线相连,备机监控主机,当主机出现问题,备机接管业务。主机成为备机。优点:总有一套机器备用,保证系统运行。缺点:浪费一套机器。

双机互备:主(备)+备(主),主备机上都跑应用,应用不通互为备份,出问题时,所有应用转在一套机器上。优点:双机皆跑应用,不浪费机器。缺点:双机压力可能互不相同,当全转到一套机器上时,该机的承受能力很是问题。如配置过高又造成浪费。

双机双工:主+备,跑的业务相同,系统前端进行业务负载均衡,通过平均分配把业务分散到多台机器上,而机器配置相应不至较高。当出现问题时可由前端负载均衡调整业务处理流量。

详见:https://blog.csdn.net/herry2008/article/details/1916258

(6)服务化好处:

解耦后进行分而治之提高安全性和并发性、提高代码复用性、屏蔽底层复杂度、调用方便

1. 路由策略:

应用层:nginx-轮询、加权轮询、IP值哈希等

服务层:dubbo-轮询、随机、一致性哈希、leastactive等

消息队列:kafka-生产者按照指定分区策略、默认的随机均衡策略等发送消息到分区;

缓存客户端:redic-哈希取模策略,jedis-一致性哈希

数据层:常用的有取模策略、分区策略等;

注:如果后端有缓存,则最好应用层选ip哈希、服务层一致性哈希、缓存哈希策略都可;

2. 存储或持久方式:??

zookeeper:分层文件系统目录树结构,事务日志和快照文件;

redis: RDB和AOF

kafka:文件结构,所以存储量很大;

3. 服务降级场景和分类:

http://jinnianshilongnian.iteye.com/blog/2306477 --- 开涛 聊聊高并发系统之降级特技

4. 分布式锁:可通过zookeeper、redis或数据库等方式实现:详见《可伸缩服务架构-李艳鹏》6.2.3

a. 数据库:

利用数据库的唯一索引来实现,插入数据成功表示获得锁;

b. Redis:

利用setnx命令和expire命令设key的超时时间;

失效时间我设置多长时间为好?如何设置的失效时间太短,方法没等执行完,锁就自动释放了,那么就会产生并发问题。如果设置的时间太长,其他获取锁的线程就可能要平白的多等一段时间。对于这个问题目前主流的做法是每获得一个锁时,只设置一个很短的超时时间,同时起一个线程在每次快要到超时时间时去刷新锁的超时时间。在释放锁的同时结束这个线程。如redis官方的分布式锁组件redisson,就是用的这种方案。

优点:性能好;

缺点是:存在锁无法释放问题、单点问题,另外不可重入问题、非阻塞问题、非公平问题都需要引入专门机制处理,实现较复杂;

c. Zookeeper:

排它锁:通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除掉自己创建的distribute_lock 节点就释放出锁。

共享锁:即不同事务可同时读,而更新操作必须在当前没有任何事务进行读写操作情况下进行;/distribute_lock 已经预先存在,所有客户端在它下面创建临时顺序节点(/shared_lock/host1-R/W-序号),获取/shared_lock子节点列表,判断当前是否是写请求,如果是读请求,则判断当前目录下有没有比自己序号小的写节点,如果没有则获得锁,如果有则监听改写节点;如果当前是写请求,判断是否序号最小和监听比自己小的节点来实现;

公平锁:在lock目录下,A要获取锁则建立临时顺序节点,然后判断是否是最小节点,如是则获取成功,退出后自动删除;B要获取锁同样流程,如果不是最小节点,则设置监听比自己值小的节点;

优点:有效的解决锁无法释放的问题、不可重入问题、非公平问题、单点问题、非阻塞问题;

缺点:性能较缓存低,每次在创建锁和释放锁的过程中,需要动态创建、销毁临时节点来实现锁功能。ZK中创建和删除节点只能通过Leader服务器来执行,然后将数据同不到所有的Follower机器上。

d. 分布式锁应用场景:

分布式定时任务(保证同一时刻只有一个集群定时任务在执行)、分布式缓存中修改变量;

其他:

https://blog.csdn.net/u010963948/article/details/79006572 分布式锁的几种使用方式(redis、zookeeper、数据库) 好!!!

https://blog.csdn.net/xlgen157387/article/details/79036337 分布式锁简单入门以及三种实现方式介绍

https://www.zhihu.com/question/62598701 redis和zookeeper有什么联系吗?

5. 分布式ID

(0)要求:

a. 全局唯一性:不能出现重复的ID号,既然是唯一标识,这是最基本的要求。

b. 粗略有序:如果在分布式环境中做到完全有序,需要用到锁等,考虑到性能,采用粗略有序,具体分为秒级有序和毫秒级有序;

c. 可反解:即生成ID服务提供反解方法,这样在存储时就能以十进制存储,省下传统timestamp类字段的占用空间了;

d. 可伸缩:中心发布模式时可进行集群部署,这样在生成ID里就必须包含机器ID;

(b. 趋势递增:在MySQL InnoDB引擎中使用的是聚集索引,由于多数RDBMS使用B-tree的数据结构来存储索引数据,在主键的选择上面我们应该尽量使用有序的主键保证写入性能。

(c. 单调递增:保证下一个ID一定大于上一个ID,例如事务版本号、IM增量消息、排序等特殊需求)

d. 信息安全:如果ID是连续的,恶意用户的扒取工作就非常容易做了,直接按照顺序下载指定URL即可;如果是订单号就更危险了,竞对可以直接知道我们一天的单量。所以在一些应用场景下,会需要ID无规则、不规则。

上述123对应三类不同的场景,3和4需求还是互斥的,无法使用同一个方案满足。

(1) 方案总结:

生成全局唯一ID方案:引入全局ID生成服务、通过时间戳、依靠特定算法生成UUID等3种方案;

(2) 方案一:UUID:

简介:共128位,3部分生成:当前日期和时间+时钟序列+全局唯一机器识别号如网卡MAC地址;UUID标准型式包含32个16进制数字,分为五段,形式为8-4-4-4-12的36个字符,示例:550e8400-e29b-41d4-a716-446655440000,到目前为止业界一共有5种方式生成UUID;

优点:性能非常高,本地生成,没有网络消耗;

缺点:--太长不易于存储,32字符16个字节128位; --不具备有序性,会导致在写入B+树索引的时候有过多的随机操作(连续的ID会产生部分顺序写),另外,由于在写入时不能产生有顺讯的append操作,而需要进行insert操作,将读取整个B+数节点到内存,在插入记录完成后将整个节点写回磁盘,这种操作在记录占用空间比较大的情况下性能下降明显;

参考:https://blog.csdn.net/xinghuo0007/article/details/72868799 -- UUID生成方法

(3) 方案二:基于数据库实现

简介:设置不同初始值和相同增长步长来实现,即4个数据库,初始值为,0,1,2,3,步长为4;

缺点:--水平扩展较难;--对数据库压力较大,每获取一次都会读写一次数据库; --只有趋势递增,没有单调递增;

(4) 方案三:类snowflake方案---好!!

简介:共64位,3部分组成:0位不用+41位时间戳+10位workerID+12位自增序列;其中:10位机器ID,可手动配置,或通过zookeeper创建持久顺序节点后取回顺序号当做自己的workerId; 41位时间戳:以某一时间为基准,当前时间减去该时间生成,40位毫秒级可支撑34年,41位可支撑68年) ,最后生成的是十进制数,如3279458774233907200

优点:--不依赖第三方,性能都很高; --可以根据自身特性分配bit位,非常灵活;--毫秒为在高位,自增序列低位,整个ID是趋势递增;

缺点:强依赖时钟,如果机器时钟回拨,会导致发号重复;每毫秒自增序列归0问题;

改进方案:leaf-snowflake方案:即对snowflake强依赖的时钟问题,进行了处理;通过间隔3秒上报时钟到zookeeper,并判断是否小于上次上报的时间来判断是否有过大幅回拨,如果是新加入节点,则访问其他节点时间并计算平均值进行对比;失败则抛异常并不提供服务或报警;

参见:https://tech.meituan.com/MT_Leaf.html 美团点评分布式ID生成系统 -- 好!!

参见:《可伸缩服务架构:框架与中间件》李彦鹏----设计一款永不重复的高性能ID发号器 --- 好!!!

(9) Mycat提供的全局主键方式如下:

1. 本地文件方式:使用服务器本地磁盘文件的方式;2. 数据库方式:使用数据库的方式;3. 本地时间戳方式:使用时间戳方式;4. 分布式zookeeper生成ID

详见:https://www.linuxba.com/archives/8002#22 Mycat全局主键

问题

可行性

 

基于redis

单点问题,redis重启问题等

较高,公司有项目使用

给予DB(每次生成多个使用时去取出来)

单点问题,并发量问题

低并发,数据量较小的可以使用

UUID

暂用存储空间比较大,非可排序的,体现不出增长的趋势

较高

twitter snowflake

Xx年以后可能存在重复问题,需要配置生产参数

高,分布式的没单点故障问题,时间上是递增的。推荐

基于DB步长的方式

不是所有数据库都支持

6.服务发布方式:

(1)嵌入式发布模式:即提供一个本地Jar包;

(2)中心服务器发布模式:客户端调用服务器;

(3)REST发布模式:中心服务器通过RestfulAPI导出服务,供非java客户端调用;

7. 分布式session一致性

session同步法:多台web-server相互同步数据

客户端存储法:一个用户只存储自己的数据

反向代理hash一致性:四层hash和七层hash都可以做,保证一个用户的请求落在一台web-server上

后端统一存储:web-server重启和扩容,session也不会丢失

8. 大量定时任务如何高效触发?

https://mp.weixin.qq.com/s/mvFwjgxliwx808Hn_9ruEA 10w定时任务,如何高效触发超时 好!!!

http://blog.51cto.com/wenshengzhu/2106623 环形队列高效触发大量超时任务的算法实现

猜你喜欢

转载自blog.csdn.net/zxb448126/article/details/81191508