SimpleRedis
实习这么长时间,学习了这么关于项目的,对于一个项目来说,现在我应该注意什么,要参考什么
项目需求
- 完成各种数据结构,使用C++去实现
- 进行单元测试,对各个数据结构进行单元测试的使用,并且尽量能够总结一个qps,并发量测试出来
- 代码能否编译成对应的lib文件或者说是动态库的形势,提供给其他人使用?
侵入式数据结构
优点
- 对于非侵入式数据结构来说,数据结构存储的是用户传递的副本(会发生拷贝),但是侵入式数据结构存储的不是数据结构的副本,而是存储对象的本身,对象插入数据容器的数据需要由对象本身来提供
- 根本不会出现调用任何内存分配相关的问题(因为侵入式数据结构的数据由外部进行管理,压根没有析构函数)
- 提供可预见性,不会进行内存管理(内存管理是不可预见的操作),管理起来要比非侵入式数据结构要好
- 更快的访问速度,完全没有内存分配,内存访问要快得多
- 存储对象如果不能copy的情况下也能使用侵入式数据结构,(因为非侵入式数据结构需要copy)
缺点
- 存储的是对象本身,对象本身需要改动,需要改动对象的内存布局,插入两个指针,sizeof的数据肯定要大
- 数据结构不会进行内存管理,用户要独立于容器之外要管理对象的生命周期
- 编写难度要不非侵入式数据结构要大
container_of
侵入式数据结构中一个数据是包含两个部分的,一个是数据本身,另一个是数据的前后指针,这里就需要偏移列表节点来获取真正的容器数据
Node* my_node = lookup_function();
MyRealData* my_data = container_of(my_node, MyData, node);
// ^ptr ^type ^member
#define container_of(ptr, T, member) ({ \
const typeof( ((T *)0)->member ) *__mptr = (ptr); \
(T *)( (char *)__mptr - offsetof(T, member) );})
数据结构
HashTable 哈希表
对于一个KV存储的数据结构,哈希表的查询,查找的时间复杂度都是\(O(1)\)的,但是实现方式有两种
- 开放寻址法
- 很显然,如果负载因子很多的话,那么其时间复杂度就会直接变大
- 链式法:
- 时间复杂度非常均匀,实现也非常简单
- 数组大小通常是2的次幂,
- 均摊成本是\(O(1)\),但是调整大小依旧是\(O(n)\),因为调整的时候是将其移动到另一个新表上
AVL树
- 为什么选择这个数据结构?
- 自平衡,而且是二叉树,好实现
- 对于排序来说,是能够自动保持平衡的树,左旋右旋,完全不会旋
- 其实这个旋转还是比较好实现的,左旋和右旋其实是一样的,其实就是将两个相关节点的左儿子,右儿子,父亲搞清楚,然后更新一下对应的树的相关信息就好了
- 最后旋转出来的节点是新节点,就是最后挂出来的节点, 这里使用面向过程的思想比较好,因为对于树来说,很多节点可能是空的,换算成面向过程比较好操作
AVL排序
真正实现的是如何进行排序,这个还是比较关键的
测试
- gtest文件中进行测试
- 之后可以使用google benchmark进行测试,这个还是比较好的
- 使用工具:
valgrind进行测试: valgrind --tool=memcheck --leak-check=full ./测试文件
TTL
- redis中很多数据都是缓存的,缓存都有有一个时间的,所以这里要用一个堆来维护这个数据。
- 这里使用的是小根堆,也就是堆的root是比较小的元素
- 很显然,插入,删除的时间复杂度是\(O(logn)\)