主要逻辑:
1, 确定一个包括大小写字母、数据的字符串ls,长度为 l = 26+26+10 = 62
2, 初始化l**n个整数,并作为一个序列push到redis里
3, 当需要转换一个长url时,先从以上的序列中随机pop出一个整数i
4, 对整数i取模(除数为l),余数对应到ls的一个字母,取完模后再除以l取整,当结果等于0时停止除模,否则结果继续取模。
5, 将所有余数对应的字母按顺序排列得到一个简短的字符串ss
6, 将长url的md5哈希值作为key,将字符串ss作为value,写入redis
7, 将字符串ss作为key, 将长url作为value,写入redis
8, 将前缀(短url域名)加上字符串ss,作为短url结果返回
9, 当用户使用短url访问时,将短url中的字符串ss取出,并作为key从redis中取出长url,跳转长url
注意:
当redis中序列数字快使用完时,要及时增加(可以写个脚本随时监控,数量少于10%时就自动增加数量),切忌不能存已经用过的数字
#encoding=utf-8
import string
import redis
import hashlib
letters = string.digits + string.ascii_letters
letters_num = len(letters)
counter_key = 'url:counter'
def init(rd,num):
for i in xrange(letters_num * num):
rd.sadd('url:id:set',i)
#通过urlid取得短url对应的字符串
def get_url(urlid):
result = []
q = urlid/letters_num
r = urlid%letters_num
result.append(letters[r])
while q:
r = q%letters_num
q = q/letters_num
result = [letters[r]] + result
return ''.join(result)
#得到短url字符串
def parse_url(rd, longurl):
ret = longurl
if (longurl.startswith("http://") or longurl.startswith("https://")) and len(longurl)>7:
m = hashlib.md5()
m.update(longurl)
urlkey = m.digest()
old_param = rd.get(urlkey)
if old_param:
ret = old_param
else:
urlid = int(rd.spop('url:id:set'))
param = get_url(urlid)
rd.incr(counter_key, 1)
rd.set(param,longurl)
rd.set(urlkey,param)
ret = param
print "short url:",ret
return ret
if __name__ == "__main__":
url = "http://www.google.com/"
rd = redis.redis('127.0.0.1',6379,db=0)
init(rd,3)
parse_url(rd,url)