Skip to content

Commit ebc42d9

Browse files
committed
feat: add redis-hash-shorten-url.md
利用 Redis Hash 实现短网址服务
1 parent 3decff6 commit ebc42d9

File tree

2 files changed

+130
-1
lines changed

2 files changed

+130
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@
3030
### 3. [Set 集合](/docs/redis-set-introduction.md)
3131

3232
### 4. [Sorted Sets 有序集合](/docs/redis-sorted-set-introduction.md)
33-
- [社交网站经常会有粉丝关注的功能,用 Redis 怎么实现?](/docs/redis-sorted-set-sns-follow.md)
33+
- [社交网站通常会有粉丝关注的功能,用 Redis 怎么实现?](/docs/redis-sorted-set-sns-follow.md)
3434

3535
### 5. [Hash 哈希](/docs/redis-hash-introduction.md)
3636
- [登录会话,用 Redis 该怎么做?](/docs/redis-hash-session-token.md)
37+
- [如何使用 Redis 实现短网址服务?](/docs/redis-hash-shorten-url.md)
3738

3839
### 6. [HyperLogLog](/docs/redis-hyperLogLog-introduction.md)
3940

docs/redis-hash-shorten-url.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# 利用 Redis 哈希实现短网址
2+
3+
## 代码实现
4+
| [Python](#Python-版本) | [Java](#Java-版本) |
5+
|---|---|
6+
7+
### Python 版本
8+
```python
9+
from redis import Redis
10+
11+
12+
# 10进制数转换为36进制字符串
13+
def base10_to_base36(number: int) -> str:
14+
alphabets = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
15+
result = ''
16+
while number != 0:
17+
number, i = divmod(number, 36)
18+
result = alphabets[i] + result
19+
20+
return result or alphabets[0]
21+
22+
23+
URL_HASH_SHORT_SOURCE_KEY = 'url_hash:short_source'
24+
ID_COUNTER = 'short_url:id_counter'
25+
26+
27+
class URLShorten:
28+
29+
def __init__(self, client: Redis):
30+
self.client = client
31+
# 设置初始ID值,保留1-5位的短码,从6位的短码开始生成
32+
self.client.set(ID_COUNTER, 36 ** 5 - 1)
33+
34+
def shorten(self, source_url: str) -> str:
35+
"""对源网址进行缩短,返回短网址ID"""
36+
new_id = self.client.incr(ID_COUNTER)
37+
short_id = base10_to_base36(new_id)
38+
self.client.hset(URL_HASH_SHORT_SOURCE_KEY, short_id, source_url)
39+
return short_id
40+
41+
def restore(self, short_id: str) -> str:
42+
"""根据短网址ID,返回对应的源网址"""
43+
return self.client.hget(URL_HASH_SHORT_SOURCE_KEY, short_id)
44+
45+
46+
if __name__ == '__main__':
47+
redis = Redis(decode_responses=True)
48+
url_shorten = URLShorten(redis)
49+
50+
short_id = url_shorten.shorten('https://github.com/yanglbme')
51+
print(short_id) # 100000
52+
source_url = url_shorten.restore(short_id)
53+
print(source_url) # https://github.com/yanglbme
54+
55+
print(url_shorten.shorten('https://doocs.github.io')) # 100001
56+
```
57+
58+
### Java 版本
59+
```java
60+
import redis.clients.jedis.Jedis;
61+
62+
public class URLShorten {
63+
private Jedis client;
64+
65+
private final String URL_HASH_SHORT_SOURCE_KEY = "url_hash:short_source";
66+
private final String ID_COUNTER = "short_url:id_counter";
67+
68+
/**
69+
* 将10进制数转换为36进制字符串
70+
*
71+
* @param number 10进制数
72+
* @return 36进制字符串
73+
*/
74+
private String base10ToBase36(long number) {
75+
String alphabets = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
76+
char[] chars = alphabets.toCharArray();
77+
StringBuilder result = new StringBuilder();
78+
while (number != 0) {
79+
int i = (int) number % 36;
80+
number /= 36;
81+
result.insert(0, chars[i]);
82+
}
83+
return result.toString();
84+
}
85+
86+
public URLShorten(Jedis client) {
87+
this.client = client;
88+
// 设置初始ID值,保留1-5位的短码,从6位的短码开始生成
89+
this.client.set(ID_COUNTER, String.valueOf((long) Math.pow(36, 5) - 1));
90+
}
91+
92+
/**
93+
* 对源网址进行缩短,返回短网址ID
94+
*
95+
* @param sourceUrl 源网址
96+
* @return 短网址ID
97+
*/
98+
public String shorten(String sourceUrl) {
99+
long newId = client.incr(ID_COUNTER);
100+
String shortId = base10ToBase36(newId);
101+
client.hset(URL_HASH_SHORT_SOURCE_KEY, shortId, sourceUrl);
102+
return shortId;
103+
}
104+
105+
/**
106+
* 根据短网址ID,返回对应的源网址
107+
*
108+
* @param shortId 短网址ID
109+
* @return 源网址
110+
*/
111+
public String restore(String shortId) {
112+
return client.hget(URL_HASH_SHORT_SOURCE_KEY, shortId);
113+
}
114+
115+
public static void main(String[] args) {
116+
Jedis client = new Jedis();
117+
URLShorten urlShorten = new URLShorten(client);
118+
119+
String shortId = urlShorten.shorten("https://github.com/yanglbme");
120+
System.out.println(shortId); // 100000
121+
String sourceUrl = urlShorten.restore(shortId);
122+
System.out.println(sourceUrl); // https://github.com/yanglbme
123+
124+
System.out.println(urlShorten.shorten("https://doocs.github.io")); // 100001
125+
126+
}
127+
}
128+
```

0 commit comments

Comments
 (0)