scenario:

分享链接长度过长,字数限制

google url shortener, bitly

根据long url生成一个short url

根据short url还原long url。访问http://bit.ly/跳转到

确认的问题:

long url和short url之间必须是一一对应的关系吗

short url长时间没人用需要释放吗?X

 

QPS+storage:

QPS:微博日活跃用户100M,average write qps = 100M * 0.1/86400 ~ 100, peak 200

average read qps = 100M * 1 / 86400 ~1k peak 2k

2k QPS一台ssd支持的mysql

推算每天产生新的url所占存储: 100M*0.1 ~10M条,每一条url长度平均100算,共1G, 1T的硬盘可以用3年

 

service:

TinyUrl只有一个UrlService

函数设计:

UrlService.encode(long_url)

UrlService.decode(short_url)

访问端口设计:

GET/<short_url>

  return a http redirect response

POST/data/shorten

  data = {url:http://xxx}

  return a short url

 

storage:

select选存储结构

schema细化数据表

sql or nosql

  1. 是否支持transaction x nosql+1
  2. 是否需要sql query x nosql+1
  3. 是否想偷懒 x nosql+1
  4. 2kQPS, cache优化 sql+1
  5. scaliability 存储和qps要求不高,单机可以搞定 sql+1
  6. sequential id 取决于用什么算法,sql提供

算法是什么?

算法1:hash function

long url的MD5的最后6位, 有冲突

算法2:随机生成shorturl + 数据库去重

随机一个6位url,如果没被用过,就绑定longurl。优点:实现简单。缺点:生成速度随着短地址越来越多变得越来越慢。

算法3: 进制转换base62

base62:

将6位的short url看作一个62进制数(0-9,a-z, A-Z)

每个short url对应到一个整数

该整数对应数据库表的primary key - sequential id - id to short url

6位可以表示的不同的url:62^6 = 57B = 570亿

int shortURLtoID(String shortURL) {

  int id = 0;

  for (int i = 0; i < shortURL.length(); i++) {

    id = id * 62 + toBase62(shortURL.charAt(i));

  }

  return id;

}

String idToShortURL(int id) {

  String chars = "0123..9abcd..zABCD..Z";

  String short_url = "";

  while (id > 0) {

    short_url = chars.charAt(id % 62) + short_url;

    id = id / 62;

  }

  while (short_url.length() < 6) {

    short_url = "0" + short_url;

  }

  return short_url;

} 

优点:效率高,缺点:依赖于全局的自增id 

 

随机生成🆚禁止转换

基于随机生成:选用nosql,cassandra, 需要建立两张表(大多数nosql不支持多重索引multi-index)

第一张表:根据long查short

row_key=longUrl, column_key=shortUrl, value=null or timestamp

第二张表:根据short查long

row_key=longUrl, column_key=shortUrl, value=null or timestamp

 

对于禁止转换:

需要用到自增id,只能用sql型数据库

id longUrl(inded = true)

shortUrl可以不存储在表单里,因为可以根据id来进行换算。

 

scale:

how to reduce response time?

读多写少

利用cache aside

缓存里需要存两类数据: long to short, short to long

利用地理位置信息提速

  优化服务器访问速度:不同地区,使用不同的web服务器,通过dns解析不同地区的用户到不同的服务器

  优化数据访问速度:使用centrailized mysql + distributed memcache。一个mysql配多个memcached,memcahced跨地区分布

usa  分配不同的ip地址

  client ->DNS->web server<->memcached(hit rate高)

     <---

            ||

          shared db(比较快)

            ||

cn  client ->DNS->web server<->memcached

     <---

 不适用于用户1次请求会产生多次数据库需求。不如访问远端的web server(延迟1次),web server和db不会延迟。

 

How to scale? 分布式架构

什么时候需要多台数据库服务器?cache资源不够(hit rate低),写操作越来越多(没法通过cache优化)

增加多台数据库服务器的好处:解决存不下-storage,解决忙不过-QPS。

怎么拆分数据将数据分配到多台服务器

vertical sharding: 将多张数据表分别分配给多台机器。

  只有两个column不适用

horizontal sharding: 

  用id/shortUrl做sharding key: long to short的时候为了查重,广播给n台数据库查询

  用longUrl做sharding key: short to long查询时,广播给n台数据库查询

如果一个long可以对应多个short:

  使用cache缓存所有的long to short

  创建short url时候,如果cache miss则去之介创建新的short url

如果一个long只能对应一个short:

  随机生成算法: 两张表单一张long to short, 一张short to long。

  base62进制转换法:多台机器之间如何维护一个全局自增的id??一般mysql只支持一台机器实现全局自增id。专门一台数据库只负责自增id服务。不存储真实数据。避免single point failure 可能需要多台数据库(master slave)    另一种方法用zookeeper

  使用hash(long_url) % 62 作为sharding key, 并放到short url(7位)。可以同时通过short_url和long_url得到sharding key。

 

usa  分配不同的ip地址

  client ->DNS->web server<->memcached(hit rate高)

     <---

            ||

    shared db0   shared db1  shared db2  shared db3

            ||

cn  client ->DNS->web server<->memcached

     <---

 

进一步优化:

web server与db之间的通信。centralized db set中心化的服务器集群与跨地域的web server之间通信较慢。

中国用户一般访问中国的网站。可以按照地域信息进行sharding。

posted on 2024-01-23 05:23  dddddcoke  阅读(8)  评论(0编辑  收藏  举报