diff --git a/docs/Redis/redis-sds.md b/docs/Redis/redis-sds.md index 863825f..c81e75f 100644 --- a/docs/Redis/redis-sds.md +++ b/docs/Redis/redis-sds.md @@ -280,12 +280,4 @@ sds sdsMakeRoomFor(sds s, size_t addlen) { 1. SDS 返回的是指向 buf 的指针,兼容了 C 语言操作字符串的函数,读取内容时,通过 len 属性来限制读取的长度,不受 `\0` 影响,从而保证二进制安全; 2. Redis 根据字符串长度的不同,定义了多种数据结构,包括:sdshdr5/sdshdr8/sdshdr16/sdshdr32/sdshdr64。 -3. SDS 在设计字符串修改出会调用 `sdsMakeRoomFor` 函数进行检查,根据不同情况进行扩容。 - -全文完! - -**希望本文对大家有所帮助。如果感觉本文有帮助,有劳转发或点一下“在看”!让更多人收获知识!** - ---- - -长按识别下图二维码,关注公众号「**Doocs 开源社区**」,第一时间跟你们分享好玩、实用的技术文章与业内最新资讯。 +3. SDS 在设计字符串修改出会调用 `sdsMakeRoomFor` 函数进行检查,根据不同情况进行扩容。 \ No newline at end of file diff --git a/docs/Sentinel/Sentinel时间窗口的实现.md b/docs/Sentinel/Sentinel时间窗口的实现.md index a2cf032..0de6abb 100644 --- a/docs/Sentinel/Sentinel时间窗口的实现.md +++ b/docs/Sentinel/Sentinel时间窗口的实现.md @@ -3,25 +3,27 @@ 在 Sentinel 中,主要是通过 LeapArray 类来实现滑动时间窗口的实现和选择。在 sentinel 的这个获取时间窗口并为时间窗口添加指标的过程中,主要的流程为: - 根据当前时间选择当前时间应该定位当前时间应该属于的时间窗口 id。 -- 根据时间窗口 id 获取时间窗口。这里可能会存在三种情况: +- 根据时间窗口 id 获取时间窗口。这里可能会存在四种情况: 1. 时间窗口还未建立,那么将会为此次流量的进入建立一个新的时间窗口返回,并且接下来这个时间窗口内的获取请求都将返回该窗口。 2. 时间窗口已经建立的情况下,将会直接获取已经存在的符合条件的时间窗口。 3. 时间窗口可能已经存在,但是当前获取的时间窗口已经过期,需要加锁,并重置当前时间窗口。 4. 当前进入的时间已经远远落后当前的时间,目标时间窗口已经被 reset 更新成更新的时间窗口,那么将不会返回目标时间窗口,而是返回一个新的空的时间窗口进行统计,这个时间窗口不会再被重复利用。 - 其中的第四个情况表明,sentinel 的滑动时间窗口是有时间范围的,这也是为了尽量减少 sentinel 的所占用的内存,默认情况下 sentinel 的采取的时间长度为 1 分钟和 1 秒钟。这里的实现与 LeapArray 类的结构非常有关系。 + +其中的第四个情况表明,sentinel 的滑动时间窗口是有时间范围的,这也是为了尽量减少 sentinel 的所占用的内存,默认情况下 sentinel 的采取的时间长度为 1 分钟和 1 秒钟。这里的实现与 LeapArray 类的结构非常有关系。 ```java protected final AtomicReferenceArray> array; ``` -在 LeapArray 中,时间窗口的存放通过一个由 AtomicReferenceArray 实现的 array 来实现。AtomicReferenceArray 支持原子读取和写入,并支持通过 cas 来为指定位置的成员进行更新。在时间窗口的创建并放回 array 的过程中,也就是上文的第一步,就是通过 AtomicReferenceArray 的 compareAndSet()方法来实现,保证并发下的线程安全。并发情况下,通过 cas 更新失败的线程将会回到就绪态,在下一次婚欢得到已经初始化完成的时间窗口。 +在 LeapArray 中,时间窗口的存放通过一个由 AtomicReferenceArray 实现的 array 来实现。AtomicReferenceArray 支持原子读取和写入,并支持通过 cas 来为指定位置的成员进行更新。在时间窗口的创建并放回 array 的过程中,也就是上文的第一步,就是通过 AtomicReferenceArray 的 `compareAndSet()` 方法来实现,保证并发下的线程安全。并发情况下,通过 cas 更新失败的线程将会回到就绪态,在下一次循环得到已经初始化完成的时间窗口。 ```java private final ReentrantLock updateLock = new ReentrantLock(); ``` -此处的 updateLock 是专门在上述的第三个情况来进行加锁的,只有成功得到锁的线程才会对过期的时间窗口进行 reset 操作,其他没有成功获取的线程将不会挂起等待,而是通过 yield()方法回到就绪态在下一次的循环尝试重新获取该位置的时间窗口。在下一次获取该锁的线程可能已经完成了,那么将会执行上述第二步,否则继续回到就绪态等待下一次循环中再次获取该时间窗口。 +此处的 updateLock 是专门在上述的第三个情况来进行加锁的,只有成功得到锁的线程才会对过期的时间窗口进行 reset 操作,其他没有成功获取的线程将不会挂起等待,而是通过 `yield()` 方法回到就绪态,在下一次的循环尝试重新获取该位置的时间窗口。在下一次获取该锁的线程可能已经完成了,那么将会执行上述第二步,否则继续回到就绪态等待下一次循环中再次获取该时间窗口。 + 以上两个数据结构是 LeapArray 类实现时间窗口在高并发下准确获取时间窗口并更新的关键。 ## 以秒级别的时间窗口举个例子