1、背景分析html
二维码的出现使资源传输由原来的USB拷贝转变为二维码扫描访问或下载。为下载资源提供短网址服务,需将短网址生成二维码。资源数据量预计可达10亿级别,日新增数据1000万左右,每秒并发访问数预计2000个链接,响应时间在0.1秒之内。mysql
2、基本原理redis
将原始地址转换为短网址算法
原始网址→网址缩短→短网址sql
将短网址转换为原始网址数据库
短网址→短网址还原→原始网址缓存
关键问题服务器
将原始地址转换为不重复的6位地址标志,海量数据的高并发读写。架构
3、项目实现并发
短网址实现方案
实现短网址服务,首先要将海量的连接数据转化为不重复的6位字符。
(1)哈希算法。哈希算法相对简单,具体算法以下:
①将原网址md5转换成32位哈希码,分为4段,每段8字节。
②对这四短网址进行循环处理,取8个字节,将其当作16进制串与0x3fffffff(30位1)与操做,即超过30位的忽略处理。
③将30位生成6段,每5位数字做为字母表在索引取得特定字符,依次进行获取6位字符串。
④总的md5串能够得到4个6位串,取任意一个就可做为这个长url的短url地址。这种方法实现起来简单,可是有较高的重复度。
(2)62位字符表示。把数字和字符组合成必定的映射,就能够产生惟一的字符串,再利用洗牌算法,把原字符串打乱后保存,对应位置的组合字符串就会是无序的组合。
大数据存储解决方案
在本项目中,主要存储数据有资源下载地址及引用页地址,预估资源下载地址长度为150个字符,引用页地址长度为50字符,二者存起来共200字符,再加上数据库自身结构占用的空间及其余信息,如时间、ID等,存储一条数据最少须要250个字节。从当前访问量来看,预计数据将达到10亿条。
总数据量 = 250 * 10^9 /(1024*1024*1024)= 230G 当前采用的是mysql架构, 10亿条数据远远超过了其处理能力。所以要对数据库进行分库分表,将表大小限定为10万条数据,每一个数据库1000张表,数据库随着数据的增加而扩展,表中的ID进行自增加,经过数据库ID、表ID、数据ID三者就能够惟一肯定条数据,将这个值转换成62进制就得出了惟一的短连接地址。
合成ID算法代码:($database_id*self::database_tables*self::table_rows)+$row_id+ ($table_id*self::table_rows);
每一个数据库将存储1000*100000=1亿条数据,数据将分布在10台机器上,10台机器将分解高峰阶段的每秒2000个并发读写操做。这种算法在初期可能会对单台机器形成过载,可采用逐步加压的方式,当数据库服务器增多后可所有开放。
高并发解决方案
应对每秒2000次的并发访问须要服务器具备快速的读写及负载均衡能力,主要须要解决两方面的问题:用户在建立短网址时,需确认该资源没有建立过;当用户在访问一个短网址时,服务器需快速响应。从数据库直接读取没法知足速度需求,同时会形成服务器过载致使系统崩溃。所以,须要将资源url放到内存中,使用内快进行快速读取。
关键问题解决方式
(1)问题一解决方案。因为数据是先有ID后有短网址,没法经过资源地址反查到短网址,所以,须要使用一个内存映射,将资源与短网址(数据ID)联系起来。操做流程:原始网址→16字节长度的原始二进制md5→从redis中查找是否存在数据ID→从内存缓存或数据库中取出数据→判断数据库中的地址是否与原网址相同→不一样则插入数据库中,创建16字节长度原始二进制md5与数据ID创建联系存入redis中。
(2)问题二解决方案。将热数据放入缓存中,减轻数据库负载,限制一天过时时间,能够防止内存使用过大。操做流程:短网址→查找内存→未找到将短网址转为ID→从数据库中查找→存入缓存→返回数据。
4、小结
短网址服务是一个比较复杂的项目,生成短6位短码是关键点,采用数据ID递增进行62位转换的方式,可简单有效地实现需求。