-
Notifications
You must be signed in to change notification settings - Fork 2
/
README
74 lines (60 loc) · 4.72 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
第一次写大型的C应用,有些地方做的不太完善。说一下基本思路
题目的大意是需要做一个有序的内存应用。中间我实现了三个基本的数据结构
基本字符串类型str,拉链式解决冲突的哈希表hashmap,一个跳表skiplist
每个跳表的node都会用hashmap存储起来,这样加速了查找和删除。这个方法
学习的是redis的zset。因为set还是需要找到对应的点。所以时间复杂度会高一些。
这个数据结构结合成的sortmap时间复杂度如下。
1.GET O(1)
2.SET O(logn) 符合跳表的插入操作的时间复杂度。
3.DEL O(1)
4.SCAN O(n)
为了防止大量的数据输入和输出,解决一个包体无法容纳的情况下我们为每一个connect 到服务器的client建立了一个client结构。内容包括每一个client的fd,输入缓冲inbuf以及 输入缓冲现在的长度inlen,输出缓冲outbuf以及输出缓冲已经消费的长度outlen。
serverinfo是server的主要数据结构。 主要保存了多路复用器的eventloop和主要存储结构
sortmap(skiplist和hashmap的合体)主要监听的fd以及客户端的数量client_channel(暂时未用到)
网络注册流程如下:
在初始化进程时,我们会在eventloop对于listenfd注册一个读监听。
当有连接上来时回调acceptTcpHandler,通过accept函数创建一个新的文件fd。
创建client数据结构。保存这个连接中的读写buf以及基本信息。
针对当前的fd建立一个读监听。并且在server中增加客户端计数器。
网络读取流程如下:
在每一次有socket读请求时,网络模块会回调readQueryFromClient
将读取到的数据放到inbuf中。(针对内核缓存和读取缓存可能不一样大小的情况,我使用了一个while直到这次
缓存中的数据都被读取到为止)并将缓存中数据搬运到inbuf中。所以socket必须是非阻塞的。当返回-1并且设置 errno为eagain时知道已经读完。
启动命令解析模块,对指令(除了正确的get set del scan以外,其他的非法指令返回一个useage,)进行解
析,客户端发上来的指令是以/r/n结束。
执行指令,(调用sortmap中的get set del scan方法)
将调用结果写到outbuf中。并且对于这个fd进行些时间监听。
网络写时间处理流程:
从client的outbuf中获取数据然后写入。如果写满,但是outbuf中的数据未写完,不删除些时间。否则,删除写
时间并且清理掉outbuf,重置outlen。
附:操作和返回
命令解析失败返回
get 如果得到 返回val, 如果没有返回null
set 如果成功返回OK,如果失败返回null
del 如果成功返回OK,如果没有返回null
scan 返回所有的数据。
str 是基本的字符串类型,会自动扩容,设定了一个阀值1M,如果现在的字符串大小大于1M.那么增长速度是每次
增加1M否则每次以翻倍的速度扩容。实现了一些str通用的函数以及命令解析函数。
map 是一个哈希表。通过拉链式的方式解决冲突。默认是 1024 * 1024 * 64个哈系桶。通过CRC64哈希算法来进行
索引。实现了增删改查的功能,但是没有进行自动扩容的方法的实现。(时间不足,要实现一个高可用的rehash)
还是有一些工作量。
skiplist 标准的跳表。实现了增删改查。改造了一下,key不能重复。
测试:
对于所有结构的增删改查都进行了测试。
视同telnent测试了大量插入并且scan。
对于str模块和sortmap模块添加了模块测试。分别是str_test()和sortmap_test模块。
客户端:
加了一个客户端模块,通过从stdin读入数据,执行后到stdout输出。
未完成:
多进程调用或者槽点分派,两者选一可以实现多进程
刷盘(可以将set和del全部记录下下来)时间原因没做
hashmap的rehash过程。
所有的数据结构都是唯一实现,比如skiplist只支持str,多路复用器只支持epoll。并没有使用函数指针进行“多态”
malloc和free虽然我已经收集到了一起,但是并没有对已使用内存进行统计。
线程中没有时间事件。
下一步规划:
实现一个线程池,增加系统对多线程的支持
再多线程调度下,使用乐观锁,进行行级锁定。保证在线程安全。
(线程池完成,进行了初步测试,准备加入一些单元测试) 2018 12 31
(增加了一些对线程池的测试,下一步将线程池加入到存储结构中。并且保证并发安全。因为需要准备一下面试,这两天要看看书,可能需要看两天书。) 2018 1 1
(今天没有忍住补充了一点线程池监控,并且把命令处理的函数移入了线程池。后期加一些乐观锁来保证输入输出buf的安全。)2018 1 2