Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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)

AltStyle によって変換されたページ (->オリジナル) /