Skip to content

Commit

Permalink
db
Browse files Browse the repository at this point in the history
  • Loading branch information
deipss committed Feb 20, 2024
1 parent 91cbca6 commit 6016c71
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 25 deletions.
19 changes: 19 additions & 0 deletions docs/Database/B+树.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
layout: default
title: B+树
parent: Database
nav_order: 8
---

# B+树
定义:
B+树是一种数据结构,是一个N叉排序树,每个节点通常有多个孩子,一棵B+树包含根节点、内部节点和叶子节点。
根节点可能是一个叶子节点, 也可能是一个包含两个或两个以上孩子节点的节点。

B+树通常用于数据库和操作系统的文件系统中。NTFS、ReiserFS、NSS、XFS、JFS、ReFS和BFS等文件系统都在使用B+树作为元数据索引。
B+树的特点是能够保持数据稳定有序, 其插入与修改拥有较稳定的对数时间复杂度。B+树元素自底向上插入。


# 参考文献

- https://ivanzz1001.github.io/records/post/data-structure/2018/06/16/ds-bplustree
29 changes: 16 additions & 13 deletions docs/Database/Redission.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ parent: Database

利用HASH结构记录线程ID和重入次数

```shell
org.redisson.RedissonLock#tryLockInnerAsync
```java
//org.redisson.RedissonLock#tryLockInnerAsync

<T> RFuture<T> tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {
internalLockLeaseTime = unit.toMillis(leaseTime);
Expand All @@ -45,7 +45,7 @@ org.redisson.RedissonLock#tryLockInnerAsync
Collections.singletonList(getName()), internalLockLeaseTime, getLockName(threadId));
}

org.redisson.RedissonLock#unlockInnerAsync
// org.redisson.RedissonLock#unlockInnerAsync

protected RFuture<Boolean> unlockInnerAsync(long threadId) {
return evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
Expand All @@ -70,7 +70,7 @@ org.redisson.RedissonLock#tryLockInnerAsync
- 不是单一的死循环,而是通过消息订阅和信号量的方式来节省资源,收到消息或信号量,才去重试获取锁
`org.redisson.RedissonLock#tryLock(long, long, java.util.concurrent.TimeUnit)`

```shell
```java
@Override
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
long time = unit.toMillis(waitTime);
Expand All @@ -89,7 +89,8 @@ org.redisson.RedissonLock#tryLockInnerAsync
}

current = System.currentTimeMillis();
RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId); // 订阅一个通知,这个通知就是锁释放时的通知 "redis.call('publish', KEYS[2], ARGV[1]); "
// 订阅一个通知,这个通知就是锁释放时的通知 "redis.call('publish', KEYS[2], ARGV[1]); "
RFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId);
if (!subscribeFuture.await(time, TimeUnit.MILLISECONDS)) {
if (!subscribeFuture.cancel(false)) {
subscribeFuture.onComplete((res, e) -> {
Expand Down Expand Up @@ -148,11 +149,11 @@ org.redisson.RedissonLock#tryLockInnerAsync

- 获取锁之后,利用watchDog定时任务去续约

```shell
org.redisson.RedissonLock#tryAcquireAsync
org.redisson.RedissonLock#scheduleExpirationRenewal
org.redisson.RedissonLock#renewExpiration
org.redisson.RedissonLock#scheduleExpirationRenewal
```java
//org.redisson.RedissonLock#tryAcquireAsync
//org.redisson.RedissonLock#scheduleExpirationRenewal
//org.redisson.RedissonLock#renewExpiration
//org.redisson.RedissonLock#scheduleExpirationRenewal
private void renewExpiration() {
ExpirationEntry ee = EXPIRATION_RENEWAL_MAP.get(getEntryName());
if (ee == null) {
Expand Down Expand Up @@ -180,7 +181,8 @@ private void renewExpiration() {

if (res) {
// reschedule itself
renewExpiration();// 递归调用自身,会不断的续约,什么时候取消续约。在锁释放时 cancelExpirationRenewal(threadId);
// 递归调用自身,会不断的续约,什么时候取消续约。在锁释放时 cancelExpirationRenewal(threadId);
renewExpiration();
}
});
}
Expand All @@ -191,7 +193,8 @@ private void renewExpiration() {

private void scheduleExpirationRenewal(long threadId) {
ExpirationEntry entry = new ExpirationEntry();
ExpirationEntry oldEntry = EXPIRATION_RENEWAL_MAP.putIfAbsent(getEntryName(), entry);// 续约时,锁的可重入
// 续约时,锁的可重入
ExpirationEntry oldEntry = EXPIRATION_RENEWAL_MAP.putIfAbsent(getEntryName(), entry);
if (oldEntry != null) {
oldEntry.addThreadId(threadId);
} else {
Expand All @@ -217,7 +220,7 @@ private void scheduleExpirationRenewal(long threadId) {

## 5.1 续约

```shell
```java
@Override
org.redisson.RedissonMultiLock#tryLock(long, long, java.util.concurrent.TimeUnit)
public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
Expand Down
5 changes: 3 additions & 2 deletions docs/Database/Redis实践.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ parent: Database

# 1. KEY设计

- 业务名称:数据名:ID login:user:10
- 长度不超过44字节,因为KEY是由STRING保存的,STRING底层编码有INT,EMBSTR,RAW三种,EMBSTR在小于44字节时使用,采用连续内存,内存使用小
- 业务名称:数据名:ID =》 login:user:10
- 长度不超过44字节,因为KEY是由STRING保存的,STRING底层编码有INT,
EMBSTR,RAW三种,EMBSTR在小于44字节时使用,采用连续内存,内存使用小

# 2. 不使用BIG KEY

Expand Down
22 changes: 12 additions & 10 deletions docs/Database/Redis网络模型.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ parent: Database
- 只拷贝一次FD到内核空间
- 内核将就绪的FD直接拷贝到用户空间,不再用户空间自己去遍历出哪个FD是就绪的

#### 2.3.3.1. epoll LT ET
**epoll LT ET**

![io-epoll-LT.png](img%2Fio-epoll-LT.png)

#### 2.3.3.2. epoll web server
**epoll web server**

![img.png](img/epoll-web.png)

Expand All @@ -62,36 +62,38 @@ parent: Database

![img.png](img/io-asynchronized.png)

# 零COPY
# 3. 零COPY

![io-zero-copy.png](img%2Fio-zero-copy.png)

因为使用mmap技术实现零拷贝,受到一定的内存大小限制,一般在1-2个G。所以使用零拷贝技术的文件,大小一般在1G左右,
因为使用mmap技术实现零拷贝,受到一定的内存大小限制,一般在1-2个G。
所以使用零拷贝技术的文件,大小一般在1G左右,
比如rocket MQ 的commit log文件就是1G一个。
# 3. 对比

# 4. 对比

![img.png](img/io-conclusion.png)

# 4. 线程模型
# 5. 线程模型

- 只是核心业务(命令处理),是单线程,整体redis(AOF)是多线程
- 版本4.0 使用异步多线程的方式来执行删除命令
- 版本6.0 在网络通信中引入多线程,提高多核CPU的利用率

# 5. 为什么使用线程
# 6. 为什么使用线程

- redis是纯内存(微秒),没有磁盘IO(毫秒),性能瓶颈是在网络延时,不是执行速度
- 上下文切换会有开销
- 要应对多线程不安全问题

# 6. redis 网络模型
# 7. redis 网络模型

![img.png](img/redis-net-model.png)

# 7. redis 网络协议
# 8. redis 网络协议

![img.png](img/redis-io-protocol.png)

# 8. redis 网络协议-数据类型
# 9. redis 网络协议-数据类型

![img.png](img/redis-io-protocol-structure.png)

0 comments on commit 6016c71

Please sign in to comment.