diff --git a/package.json b/package.json index b6bf048..9660b58 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "server": "hexo server" }, "hexo": { - "version": "5.4.2" + "version": "5.3.0" }, "dependencies": { "hexo": "^5.0.0", diff --git "a/source/_posts/\345\220\216\345\217\260\345\270\270\350\247\201\347\255\226\347\225\245-\346\234\215\345\212\241\351\231\220\346\265\201.md" "b/source/_posts/\345\220\216\345\217\260\345\270\270\350\247\201\347\255\226\347\225\245-\346\234\215\345\212\241\351\231\220\346\265\201.md" new file mode 100644 index 0000000..53a4a44 --- /dev/null +++ "b/source/_posts/\345\220\216\345\217\260\345\270\270\350\247\201\347\255\226\347\225\245-\346\234\215\345\212\241\351\231\220\346\265\201.md" @@ -0,0 +1,16 @@ +--- +title: 后台常见策略-服务限流 +date: 2024-03-23 23:58:32 +tags: 后台常见策略 +--- + +后台服务领域内有很多通用的策略,他们的本质往往很简单,只是长时间不接触就会被我遗忘掉。这里总结下服务限流。 + +长久以来我只记得住令牌桶算法,它支持匀速发token,也允许有突发流量,就很完美。但这是算法角度,还有工程实践角度需要考虑:比如每次请求令牌,都要发起服务调用吗(也可能是redis之类的存储调用)? + +在高性能场景下,特别是公司级基础服务,一定是把大量逻辑放到SDK,服务端只承担一定的限流规则记录&&同步功能。简单分为这几种模式: +* 单次分配。每次查询是否限流,都去发起服务调用。可以想象这在高性能场景下是不可能的,白白增加主调方耗时&&基础服务负载压力。 +* 预分配。SDK定期从基础服务获取一定数量的令牌,然后主调方在本地就能判断是否需要限流。这就非常的高性能了,但是也有问题:不够精确。可能主调方的流量不均衡,大家需要的令牌数量不一致,如果预分配的策略不合适(均匀分配/按权重等),可能产生误判。 +* 先消费,后结算。SDK直接本地决定是否限流,然后定期地/异步地去基础服务里结算:我用了多少个令牌,下次还能用多少个?好处是可以应对突发流量,快速抢占令牌;坏处是,可能产生超额消费令牌。**据某些分析**,整体流量较低时,先消费后结算的方式不容易触发超额消费,反而有自己的优势:可以应对突发流量。 + +世界上的事情大多不是非黑即白,总是你中有我,我中有你。比如司内就有人把第二/三种模式混合使用,流量较低时,关注突发流量,使用模式三;较高时,关注超额问题,使用模式二。但是我觉得很花哨,不知道真实效果如何。 \ No newline at end of file diff --git "a/source/_posts/\345\220\216\345\217\260\345\270\270\350\247\201\347\255\226\347\225\245-\350\264\237\350\275\275\345\235\207\350\241\241.md" "b/source/_posts/\345\220\216\345\217\260\345\270\270\350\247\201\347\255\226\347\225\245-\350\264\237\350\275\275\345\235\207\350\241\241.md" new file mode 100644 index 0000000..a1a13e5 --- /dev/null +++ "b/source/_posts/\345\220\216\345\217\260\345\270\270\350\247\201\347\255\226\347\225\245-\350\264\237\350\275\275\345\235\207\350\241\241.md" @@ -0,0 +1,17 @@ +--- +title: 后台常见策略-负载均衡 +date: 2024-03-23 23:43:59 +tags: 后台常见策略 +--- + +后台服务领域内有很多通用的策略,他们的本质往往很简单,只是长时间不接触就会被我遗忘掉。这里总结下负载均衡。 + +负载均衡有这么几种常见方式: + +* round robin。 完全随机。 +* 按权重随机。 比如一些纯计算的任务,他们完全不依赖缓存,对应服务也是无状态的;同时我们又因为开源节流的原因,使用了一些性能较差的机器,那么就适合以机器性能为权重,随机到服务节点。 +* 一致性hash。 后台服务是有状态的,通常具有本地缓存,那么就适合使用一致性hash。 + +实战中我们都是使用一致性hash:在主调方的路由sdk内,建立hash值-虚拟节点-物理节点的映射关系。但是偶尔的,我们会遇到一些问题: +* 正常实现里,一个hash值总是对应一个物理节点。如果映射关系发生变化(机器上下线),就要承担流量迁移/重新建立缓存的开销。有时这个开销非常大,比如在推荐算法场景里,某个模型文件可能很大,重建一次要耗费很长时间(用于下载/解析)。为了减少开销,可以考虑一个hash值对应多个物理节点,然后随机路由到其中一个,这样可以使多台机器同时具有某个对象的缓存。具体怎么做呢?例如一个hash值本来对应虚拟节点X,现在路由的时候随机选区虚拟节点X-1/X/X+1,于是可以对应到3台物理节点。 +* 有时候我们想做的很精细。比如节点上线时,要给它冷启动/预热的时间,那么就要分配对应的权重。本来一个物理节点对应N个虚拟节点,现在当机器上线时,我们先给他分配1个虚拟节点,然后按照一定时间间隔,慢慢地给它增加虚拟节点,直到冷启动完成(此时对应N个节点)。冷启动期间的节点变化节奏,还可以根据机器的接口耗时/成功率来变化,不过这就跟复杂了(有时候太复杂的东西实现起来容易出bug,建议不要瞎搞)。 \ No newline at end of file