-
Notifications
You must be signed in to change notification settings - Fork 21
Explain
发现在github中已有的短链服务中,非分布式服务做到快速扩容,并且有些项目是用的redis作为数据缓存,性能上不够优秀.
短链接,通俗来说,就是将长的URL网址,通过程序计算等方式,转换为简短的网址字符串。
微博和Twitter都有140字数的限制,如果分享一个长网址,很容易就超出限制。
营销短信,字数的限制,当字数过长: 1.不美观 2.超出字符额外收费。
生成二维码的原始链接,当原始链接过长时,生成的二维码过于复杂,导致一些像素较低的手机无法扫描.
-
将长链接变为短链;
-
用户访问短链接,会跳转到正确的长链接上去。
- 短链key的生成逻辑
- 如何提高短链key生成效率
生成短链方法有很多,如: md5长链、 自增序列算法、 摘要算法、哈希法、 普通随机数。
最终本项目借鉴了 美团leaf分布式ID生成系统 整理出来了适合本项目的生成短链key逻辑 <号码段模式>
在针对生成短链key生成效率优化: 使用简化版的 Leaf-segment 数据库方案 及 双buffer优化
首先先看下 短链key生成表结构
CREATE TABLE `durl_short_num` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`max_num` int(11) NOT NULL DEFAULT '1' COMMENT '号码段开始值',
`step` int(11) NOT NULL DEFAULT '1' COMMENT '步长',
`version` int(11) NOT NULL DEFAULT '1' COMMENT '版本号',
`update_time` int(11) NOT NULL DEFAULT '0' COMMENT '数据修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短链号码段';
短链key为号码段short_num进行62进制转换后的值.
项目初始化及使用期间,每次获取一个step号段。如:200-300, 用完之后再去数据库获取新的号段,可以大大的减轻数据库的压力。
重要字段说明: max_num表示目前所被分配的短链key的最大值。 step表示每次分配的号段长度。version是一个乐观锁,每次都更新version,保证并发时数据的正确性
在多台机器,考虑获取号码段重复获取数据时使用乐观锁查询方式.
在实际线上环境,只需要把step设置得足够大,比如1000。 那么只有当1000个号被消耗完了之后才会去重新读写一次数据库。 读写数据库的频率从1减小到了1/step,大致架构如下图所示:
如果取号段的时机是在号段消耗完的时候进行的,也就意味着号段临界点的ID下发时间取决于下一次从DB取回号段的时间, 并且在这期间进来的请求也会因为DB号段没有取回来,导致线程阻塞。 如果请求DB的网络和DB的性能稳定,这种情况对系统的影响是不大的,但是假如取DB的时候网络发生抖动,或者DB发生慢查询就会导致整个系统的响应时间变慢。
为此,我们希望DB取号段的过程能够做到无阻塞,不需要在DB取号段的时候阻塞请求线程, 即当号段消费到某个点时就异步的把下一个号段加载到内存中。 而不需要等到号段用尽的时候才去更新号段。
采用双buffer的方式,服务内部有两个号段缓存区segment。 当前号段已下发10%时,如果下一个号段未更新,则另启一个更新线程去更新下一个号段。 当前号段全部下发完后,如果下个号段准备好了则切换到下个号段为当前segment接着下发,循环往复。