gitbook/Redis源码剖析与实战/docs/418672.md
2022-09-03 22:05:03 +08:00

50 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 期中测试题答案 | 这些问题你都答对了吗?
你好,我是蒋德钧。这节课,我来给你公布一下期中考试中问答题的答案。
## 第一题
Redis源码中实现的哈希表在rehash时会调用dictRehash函数。dictRehash函数的原型如下它的参数n表示本次rehash要搬移n个哈希桶bucket中的数据。假设dictRehash被调用并且n的传入值为10。但是在dictRehash查找的10个bucket中前5个bucket有数据而后5个bucket没有数据那么本次调用dictRehash是否就只搬移了前5个bucket中的数据
```plain
int dictRehash(dict *d, int n)
```
### 答案分析
当Redis哈希表在做rehash搬移数据时如果遇到空的bucket那么Redis会跳过空的bucket再查找下一个bucket。但是在dictRehash函数中是使用了empty\_visits变量来记录跳过的空bucket数量而empty\_visits的值是被初始化成n\*10也就是要搬移的bucket数量的10倍。
因此如果rehash过程中已经跳过了empty\_visits数量的空bucket那么本次dictRehash的执行就会直接返回了而不会再查找bucket。这样设计的目的也是为了**避免本次rehash的执行一直无法结束影响正常的请求处理**。
所以在题述场景中dictRehash函数会在找到50个空bucket时直接结束执行即使此时还没有完成10个bucket数据的搬移。而如果在查找的10个bucket后面紧接着就有5个bucket有数据那么本次调用dictRehash仍然搬移了10个bucket的数据。
## 第二题
Redis的事件驱动框架是基于操作系统IO多路复用机制进行了封装以Linux的epoll机制为例该机制调用epoll\_create函数创建epoll实例再调用epoll\_ctl将监听的套接字加入监听列表最后调用epoll\_wait获取就绪的套接字再进行处理。请简述Redis事件驱动框架中哪些函数和epoll机制各主要函数有对应的调用关系。
### 答案分析
Redis在initServer函数中调用了aeCreateEventLoop函数初始化事件框架其中aeCreateEventLoop函数会调用aeApiCreate函数而如果IO多路复用机制使用的是epoll机制那么aeApiCreate函数就会调用epoll\_create函数创建epoll实例。这个调用关系如下
```plain
aeCreateEventLoop --> aeApiCreate --> epoll_create
```
然后当事件驱动框架初始化完成后initServer函数就会调用aeCreateFileEvent函数而aeCreateFileEvent函数会调用aeApiAddEvent函数进而调用epoll\_ctl将监听套接字加入监听列表。这个调用关系为
```plain
aeCreateFileEvent --> aeApiAddEvent --> epoll_ctl
```
这样一来Redis server在完成初始化后就会调用aeMain函数进入事件框架的循环流程。在这个流程中**aeProcessEvents函数**会被循环调用用于不断处理事件。aeProcessEvents函数会调用aeApiPoll函数而aeApiPoll函数就会调用epoll\_wait进而获取就绪的套接字从而可以处理套接字上的事件了。这个调用关系你可以参考以下代码
```plain
aeMain --> aeProcessEvents --> aeApiPoll --> epoll_wait
```
好了,这节课就到这里。期中周转眼就过去了一大半,希望你抓住最后的几天时间,好好地巩固一下所学的内容。我们下节课再见。