zoukankan      html  css  js  c++  java
  • 短网址服务设计

    短网址服务设计

    背景

    短网址服务,用来将输入的一个长网址转换为一个短网址(比如附录中的案例),当用户请求这个短网址时,服务查询出真实的url;
    设计这么一个短网址服务,需要考虑哪些点?

    数据结构

    首先,需要考虑短网址应该如何存储,使用一个key-value结构就可以;
    key是生成的短网址,具有唯一性;
    value为原始真实网址;

    算法

    计算短网址的算法可以很简单,短网址与原始网址就只存在一个映射关系。
    从1开始递增来映射每一个网址;
    1个位上可以使用26位字母+10个数字,即36进制; 而如果也用上大写字母,就是62进制;
    当然,在计算前需要通过value来查一遍,确定是否有重复键,如果有重复,直接返回;
    那通过value如何快速定位是否有重复?再使用一个STL set来解决判重是个方法,有没有更好的方式?

    使用一个hash表或STL set保存所有的长url会消耗很大的空间;而如果不保存这个映射关系,用户针对同一个长url的多次请求都返回的是不同的短url,体验不好,也消耗短url资源;
    好的做法:保存最近一段时间(比如6小时)的长url记录,这段时间内,对同一长url的转换,返回的是同一个短url;而过期之后再做转换,返回另一个新的URL;

    确定key的长度和value的长度

    value长度可以设置在500,一般的网址不会超过这个数;
    key: t.cn/**
    key的长度决定了能够支持多少个短网址;
    如果是5位长度,能够支持6000多万的网址,6位长度就是21亿;

    数据容量

    预估数据容量
    会占用多大的空间;对于这类服务,基于效率考虑,一般是全内存操作;
    如果单机能够装下,使用单机;
    如果单机无法装下,需要分片;分片策略可以根据key的递增范围来定,也可以根据取模来确定;

    分片策略

    根据key的递增范围分片

    优点: 扩容简单,超过1个服务器的容量后就增加一台机器;
    缺点:负载可能不均衡;一般后生成的短网址访问比较频繁,造成装载早期短网址的服务器空闲;

    根据key的取模来分片

    优点:用户的负载比较均衡;
    缺点:难以扩容

    取舍:可以先预估数据容量,确定使用的服务器数,使用第二种分片方法;当数据超出预估的容量,对于超出的key再使用第一种分片方法路由到新的服务器上(打补丁)

    接口设计

    确定用户传入的接口协议,用户的输入和输出

    并发读写和数据存储

    使用什么来存放这些key-value数据?
    貌似一个STL hash map容器就可以,但map不是线程安全的,考虑加锁?
    如果实时性要求不高,可以使用AB两块内存操作,一块内存线上读,一块线下写,定期更新;
    由于用户输入了长的网址之后,需要在终端上能够显示出被转换的短网址,所有对写的实时性也是有要求的;
    要求实时,针对map可能得用上锁,或者直接使用第三方内存产品,如redis,memcache等;
    对redis的读写使用异步进一步提高并发效率;

    网络

    对于用户请求量,如果是千兆网能够满足,使用一个单线程事件循环来处理;(IO non-blocking + io multiplexing)
    如果用户请求更大,使用多个Reactor事件循环来处理,接入的reactor只负责事件的监听,连接建立后,将用户请求的处理转到后续的计算reactor中处理;
    查询和更新逻辑简单,可以直接在IO事件循环中处理(类似ngnix架构)
    如果更新逻辑复杂,考虑后台增加额外的进程/线程池,处理异步写操作;

    安全

    (可选)考虑有恶意用户,构造不存在的网址来连续触发请求,以此来占满短网址的id;
    可对网址进行合法性校验(直接访问那个网址太耗时间,不太显示)
    对同一来源用户限制请求数;

    案例

    http://t.im/ 这个短网址生成器上使用的就是36进制递增来做的:
    例如,多次输入不同的长网址,得到的短网址:
    http://t.im/vgu8
    http://t.im/vgu9
    http://t.im/vgu0
    http://t.im/vgua
    从这也可看出这个网站的并发并不大,我这几次请求都是相隔几秒的;
    这个网站也没有做特殊的网址校验规则,比如输入a.bb.ccc之类的网址,都为合法;

    后记

    以上是自己的一些想看,看过网上的一些文章后,发现有不少改进的地方:

    1. 短url的存储

    设计时使用的是字母和数字的组合,使用36进制或62进制是为了让url尽可能的短;在后台存储的时候,使用整型更为合适,
    整型比较比字符串比较要高效,像redis等第三方产品对整型的查找都有专门的优化;后台整型存储,返回给用户时,进行10进制到36进制的转换即可;

    2. 分布式发号器
    自增的发号器是单点。如果流量大了,涉及到拆分,分成多个服务器来处理;发号器同样可以扩容到多个,扩到2台,分别发单双号;第一台发单号,第二天发双号,不会重复;而扩容到10台,则分别发0~9尾号的号;

    Posted by: 大CC | 06NOV,2015
    博客:blog.me115.com [订阅]
    Github:大CC

  • 相关阅读:
    《通往衰败之路》读后感 读书笔记
    《苏世民我的经验与教训》读后感 读书笔记
    《红星照耀中国》读后感 读书笔记
    《上帝之子》读后感 读书笔记
    《两兄弟》读后感 读书笔记
    《好的经济学》读后感 读书笔记
    JSON 使用 教程
    JSON 使用
    JSON 语法
    Json
  • 原文地址:https://www.cnblogs.com/me115/p/4943234.html
Copyright © 2011-2022 走看看