diff --git a/README.md b/README.md
index 95a3ac6..84c100e 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,23 @@
-# redis_doc
\ No newline at end of file
+
+
+
+
+
+本项目用于学习Redis源码所做的笔记,便于以后查看复习。没有在Redis源码中直接写注释的原因时源码太多了,学习成本有点高,不适合我这种虽然比较菜,但是爱学习的人学习。
+
+## 目录
+
+- [简介](brief)
+ - [编译](brief/complie.md)
+ - [Redis 6新特性](brief/redis6.0.md)
+ - [Redis 7新特性](brief/redis7.0.md)
+- [动态字符串](sds)
+- [跳跃表](skiplist/readme.md)
+- [压缩表](ziplist/readme.md)
+
+
+## 特别感谢
+
+- [CN-annotation-team/redis7.0-chinese-annotated](https://github.com/CN-annotation-team/redis7.0-chinese-annotated)
+- [redis/redis](https://github.com/redis/redis)
+
diff --git a/skiplist/skiplkist.md b/skiplist/readme.md
similarity index 100%
rename from skiplist/skiplkist.md
rename to skiplist/readme.md
diff --git a/ziplist/readme.md b/ziplist/readme.md
new file mode 100644
index 0000000..0f90ba2
--- /dev/null
+++ b/ziplist/readme.md
@@ -0,0 +1,157 @@
+## 简介
+
+压缩列表ziplist本质上就是一个字节数组,是Redis为了节约内存而设计的一种线性数据结构,可以包含多个元素,每个元素可以是一个字节数组或一个整数。
+Redis的有序集合、散列和列表都直接或者间接使用了压缩列表。当有序集合或散列表的元素个数比较少,且元素都是短字符串时,Redis便使用压缩列表作为其底层数据存储结构。列表使用快速链表(quicklist)数据结构存储,而快速链表就是双向链表与压缩列表的组合。
+ziplist 压缩列表是一个特殊编码的双端链表(内存上连续),为了尽可能节省内存而设计的。ziplist 可以存储字符串或者整数值,其中整数被编码保存为实际的整数,而不是字符数组。ziplist 支持 O(1) 的时间复杂度在列表的两端进行 push 和 pop 操作。然而因为这些操作都需要对整个 ziplist 进行内存重分配(因为是一块连续的内存),所以操作的实际复杂度和 ziplist 占用的内存大小有关。在 7.0 版本里,ziplist 已经全面被 listpack 替换了(主要是因为连锁更新较影响性能)
+
+
+## 压缩列表的存储结构
+
+Redis使用字节数组表示一个压缩列表,压缩列表结构如下所示:
+
+```
+ ...
+```
+
+压缩列表各字段的含义如下:
+
+- zlbytes:是一个 32 位无符号整数(4 bytes),记录整个 ziplist 占用的内存字节数,包含 4 个字节的 zlbytes 本身。
+- zltail:是一个 32 位无符号整数(4 bytes),记录 ziplist 到尾节点的位置偏移量。通过这个偏移量我们可以直接定位到表尾节点,例如进行表尾的 pop 操作,不然得完整遍历 ziplist。
+- zllen:是一个 16 位无符号整数(2 bytes),记录 ziplist 里的节点数量。由于它设计只用 2 个字节进行存储,2 字节实际最大可以表示为 2^16 - 1 即: 65535。当数字小于它时,则 zllen 的值就是实际的节点数量(O(1) 时间复杂度), 也就是注释里的 2^16 - 2 的含义。否则当 zllen 值为 65535 时即 2^16-1,用它作为一个标识,表示需要完整遍历整个压缩列表 O(N) 时间复杂度才能计算出真实的节点数量。所以 ziplist 不适合存储过多元素(遍历计算节点数量开销很大,且我们假设它只用于元素数量较少的场景)。
+- entryX:压缩列表存储的元素,可以是字节数组或者整数,长度不限。entry的编码结构将在后面详细介绍。
+- zlend: 是一个 8 位无符号整数(1 byte),是一个特殊的标志位来标记压缩列表的结尾,0xFF(十进制表示为: 255)。其它正常节点不会有以这个字节开头的,在遍历 ziplist 的时候通过这个标记来判断是否遍历结束。
+
+### 元素的存储结构
+
+压缩列表元素的存储结构如下所示:
+```
+
+```
+每一个 ziplist entry 压缩列表节点在实际的节点数据之前都会包含两部分元数据,也叫 entry header。
+1. prevlen: 前置节点的字节长度,以支持我们从后往前遍历(通过指针偏移量定位前一个节点)
+2. encoding: 当前节点 entry-data 节点数据部分的类型和编码,例如存储的是整数还是字符串,类型下还会细分多种编码。
+
+有时候节点可以不用有 entry-data,可以在 encoding 部分直接存储节点数据。例如一些小整数,可以直接在 encoding 部分用几位来存储表示,对每一位都物尽其用。此时元素的存储结构为:
+
+```
+
+```
+当前节点的前节点字节长度,prevlen 的编码方式如下(同时我们将存储 prevlen 所需的字节数为 prevlensize,即下面的 1 或者 5 字节)
+- 如果前节点的字节长度 小于 254 字节,那么 prevlen 使用 1 个字节来保存它,一个 8 位无符号的整数。
+ ```
+
+ ```
+ - `prevlen`:前一个entry长度,介于(0,253)
+ - `encoding`:当前节点的实际数据类型以及长度
+ - `entry`:当前节点的实际数据
+- 如果前节点的字节长度 大于等于254 字节,那么 prevlen 使用 5 个字节来保存它:
+ ```
+ 0xFE <4 bytes unsigned little endian prevlen>
+ ```
+ - `0xFE`: zlend 标识,值为 254(1 字节)
+ - `<4 bytes unsigned little endian prevlen>`: 当前节点的实际长度(4 字节)
+ - ``: 当前节点的实际数据类型以及长度
+ - ``: 当前节点的实际数据
+
+压缩列表元素编码:
+
+| encoding编码 | encoding 长度 |context类型 |
+|---- |---- |---- |
+| 00 pppppp | 1 bytes | value最大长度为63字节,`pppppp`的长度为6 |
+| 01 pppppp qqqqqqqq | 2 bytes | value的最大长度16383字节 |
+| 10000000 qqqqqqqq rrrrrrrr ssssssss tttttttt| 5 bytes | value的最大长度2^32-1。第一个字节的6个低位不被使用,并且被设置为零。 |
+| 11000000 | 3 bytes | int 16 (2 bytes) |
+| 11010000 | 5 bytes | int 32 (4 bytes) |
+| 11100000 | 9 bytes | int 64 (8 bytes) |
+| 11110000 | 4 bytes | 24位整数(3 bytes) |
+| 11111110 | 2 bytes | 8位整数(1 byte) |
+| 1111xxxx | 1 byte | 0-12的无符号整数 |
+| 11111111 | 1 byte | ziplist结束 |
+
+Redis 常见的encoding:
+
+```c
+#define ZIP_STR_MASK 0xc0
+#define ZIP_INT_MASK 0x30
+#define ZIP_STR_06B (0 << 6)
+#define ZIP_STR_14B (1 << 6)
+#define ZIP_STR_32B (2 << 6)
+#define ZIP_INT_16B (0xc0 | 0<<4)
+#define ZIP_INT_32B (0xc0 | 1<<4)
+#define ZIP_INT_64B (0xc0 | 2<<4)
+#define ZIP_INT_24B (0xc0 | 3<<4)
+#define ZIP_INT_8B 0xfe
+```
+
+## 解码结构体
+对于压缩列表中的任意元素,获取前一个元素的长度、判断存储的数据类型、获取数据内容等都需要经过复杂的解码运算。解码后的结果应该被缓存起来,为此定义了结构体zlentry,用于表示解码后的压缩列表元素,单纯的用来临时存储解码之后的元素信息。
+
+```c
+typedef struct zlentry {
+ unsigned int prevrawlensize;
+ unsigned int prevrawlen;
+ unsigned int lensize;
+ unsigned int len;
+ unsigned int headersize;
+ unsigned char encoding;
+ unsigned char *p;
+} zlentry;
+```
+
+- prevrawlensize: 存储下面 prevrawlen 所需要的字节数
+- prevrawlen: 存储前一个节点的字节长度
+- len: 存储当前节点的字节长度
+- headersize: prevrawlensize + lensize 当前节点的头部字节,其实是 prevlen + encoding 两项占用的字节数
+- encoding: 存储当前节点的数据编码格式
+- p: 指向当前节点开头第一个字节的指针
+
+函数zipEntry用来解码压缩列表的元素,填充为zlentry结构体。
+
+```c
+static inline void zipEntry(unsigned char *p, zlentry *e) {
+ ZIP_DECODE_PREVLEN(p, e->prevrawlensize, e->prevrawlen);
+ ZIP_ENTRY_ENCODING(p + e->prevrawlensize, e->encoding);
+ ZIP_DECODE_LENGTH(p + e->prevrawlensize, e->encoding, e->lensize, e->len);
+ assert(e->lensize != 0);
+ e->headersize = e->prevrawlensize + e->lensize;
+ e->p = p;
+}
+```
+
+解码主要分为下面几个步骤:
+
+### 解码前节点长度
+根据 p 目前的指针,获取 entry 的 prevlen 的值;
+- 如果prevlen一个字节编码,对应字节 (ptr)[0] 的值就是 prevlen。
+- 如果prevlen五个字节编码,具体的 prevlen 是存储在后四个字节,后四个字节进行位运算获得实际的 prevlen
+
+```c
+#define ZIP_DECODE_PREVLEN(ptr, prevlensize, prevlen) do { \
+ ZIP_DECODE_PREVLENSIZE(ptr, prevlensize); \
+ if ((prevlensize) == 1) { \
+ (prevlen) = (ptr)[0]; \
+ } else { /* prevlensize == 5 */ \
+ (prevlen) = ((ptr)[4] << 24) | \
+ ((ptr)[3] << 16) | \
+ ((ptr)[2] << 8) | \
+ ((ptr)[1]); \
+ } \
+} while(0)
+```
+根据prevlensize的长度判断prevlen的长度,如果`(ptr)[0] < ZIP_BIG_PREVLEN`时(ZIP_BIG_PREVLEN=254),则prevlen长度为1,否则长度为5。
+```c
+ #define ZIP_DECODE_PREVLENSIZE(ptr, prevlensize) do { \
+ if ((ptr)[0] < ZIP_BIG_PREVLEN) { \
+ (prevlensize) = 1; \
+ } else { \
+ (prevlensize) = 5; \
+ } \
+ } while(0)
+```
+
+### 解码encoding
+
+
+### 解码长度
+
+