Skip to content

Commit

Permalink
new update of basic and design
Browse files Browse the repository at this point in the history
  • Loading branch information
rbmonster committed Dec 9, 2020
1 parent c43c072 commit 357cd75
Show file tree
Hide file tree
Showing 8 changed files with 672 additions and 126 deletions.
File renamed without changes.
89 changes: 89 additions & 0 deletions src/main/java/com/design/TINYURL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# 短连接设计

相关文章:
- https://github.com/soulmachine/system-design/blob/master/cn/tinyurl.md
- https://github.com/xitu/system-design-primer/blob/translation/solutions/system_design/pastebin/README-zh-Hans.md
- https://www.cnblogs.com/rickiyang/p/12178644.html
- https://www.zhihu.com/question/20103344/answer/573638467
- https://segmentfault.com/a/1190000006140476

## 确定问题的范围
1. 数据量,增长数据量。
2. 链接过期时间设置。
3. 使用数据库或不使用数据库保存。


## 短链接设计
### 使是否使用数据库
使用数据库,可以收集数据,进而再进行数据分析。而不适用数据库纯粹只是生成短连接服务。

### 确定短连接长度
1. 使用大小写字母+数字的62进制方案,取6~8位便可以支持上亿的不同短连接

62^6 = 568,00235584
62^7 = 35216,14606208

2. 使用32进制小写字母+数字 36位
36^8 = 3w亿


### 方案一: 摘要算法

#### 单使用md5加密
使用MD5 摘要算法进行长URL加密(分为16位和32位),获取前8个字符,当成短连接地址。
##### hash冲突
1. 加密后,必定会出现hash冲突的情况,可以对原有的url进行加减字符重新加密。或者对于加密后的md5再次md5加密。
2. 使用url+时间戳生成,生成失败后获取新的时间戳生成。

#### 混合使用MD5 与 base 62
1. 使用 MD5 来哈希用户的 IP 地址 + 时间戳
- MD5 是一个普遍用来生成一个 128-bit 长度的哈希值的一种哈希方法
2. 用 Base 62 编码 MD5 哈希值
- 对于 urls,使用 Base 62 编码 [a-zA-Z0-9] 是比较合适的, 对于每一个原始输入只会有一个 hash 结果,Base 62 是确定的(不涉及随机性)
> Base 64 是另外一个流行的编码方案,但是对于 urls,会因为额外的 + 和 - 字符串而产生一些问题

### 方案二:使用UUID的发号器方案

使用如雪花主键的UUID当成长链接对应的键,


### 数据库映射
加密后,存储数据库根据数据纬度讨论长链接与短链接的映射关系。
1. 若长链接需要区分分享的用户,地点,时间等信息,长链接与短链接以1对多的方式存储。可用于后序的数据分析。
2. 若长连接无需区分用户的类型,可直接公用相同的短链接。如何建立映射关系可见下方:
- 可选的方案为,使用LRU或者Redis带过期时间的Hash,来进行数据映射。


## 短链接跳转,301还是302重定向
这个问题主要是考察你对301和302的理解,以及**浏览器缓存**机制的理解。

301是永久重定向,302是临时重定向。短地址一经生成就不会变化,所以用301是符合http语义的。但是如果用了301, Google,百度等搜索引擎,搜索的时候会直接展示**真实地址**(即短链接对应的长连接地址,浏览器缓存),那我们就无法统计到短地址被点击的次数了,也无法收集用户的Cookie, User Agent 等信息,这些信息可以用来做很多有意思的大数据分析,也是短网址服务商的主要盈利来源。

所以,正确答案是302重定向。


## 数据库设计

使用shortlink 当成组件
```
shortlink char(7) NOT NULL
expiration_length_in_minutes int NOT NULL
created_at datetime NOT NULL
paste_path varchar(255) NOT NULL
PRIMARY KEY(shortlink)
```

### 分库分表
由于短链接可直接做进制转换,并具有唯一性

使用短连接作为sharding key,进行水平分库拆分。

另外可以基于一季度做数据归档。

### 读写分离


## 预防攻击
1. 频繁生成短链接的 使用ip黑名单屏蔽。
2. 使用redis建立长连接->ID 的缓存。
2 changes: 1 addition & 1 deletion src/main/java/com/learning/basic/CONCURRENTTOOL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### AbstractQueuedSynchronizer AQS 基础类
AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器。核心思想是
1. 如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。
1. 使用volatile修饰的statue变量表示共享资源的状态。如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。
2. 如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制 AQS 是用 CLH 队列锁实现的,即将暂时获取不到锁的线程加入到队列中。
3. CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)
4. 通过自旋+CAS获取共享资源,如果获取失败则调用调用native方法 进入park 状态。
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/com/learning/basic/CONCURRENT_APPLICATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Java并发应用

## 生产者与消费者模型



## 线程安全的类定义
1. 无状态的类:没有任何成员变量的类,如无任何方法的枚举类型。
2. 让类不可变
1. 加final关键字
2. 不提供修改成员变量,也不提供获取成员变量方法
3. 使用volatile,保证类的可见性,不能保证线程安全。适合一写多读的场景
4. 加锁和CAS,使用synchronized、lock、原子变量AtomicInteger等
1. 如StringBuffer 修改的方法都使用synchronize修饰。
2. 如concurrentHashMap 使用自旋加CAS修改。
3. 使用Atomic包的基本类型,如AtomicInteger、AtomicReference、AtmoicStampReference修饰变量。


## 单订单重复退款请求
1. synchronize修饰退款方法。
2. 缩小synchronize锁范围,使用对象锁。对象锁,创建弱引用的一个订单ID对象,放到同一的锁对象资源池中。
- 清理锁对象可以使用守护线程的方法,基于Unsafe的包操作去清除。
3. 分布式应用,使用分布式锁来处理。


### 分布式锁的处理方案

1. 数据库锁,数据库乐观锁,数据库悲观锁。

2. redis 锁 或者 ZooKeeper锁

3. 使用消息队列顺序消费,保证不重复退款
Loading

0 comments on commit 357cd75

Please sign in to comment.