初步了解Redis(一) | 青训营笔记

46 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第9天

Redis优势

在面对大流量请求时, 传统关系型数据库不能很好地解决访问压力, 容易出现崩溃的现象, 因此需要一个缓存中间件

而非关系型数据库Redis就是一个优秀的, 适合做缓存的非关系型数据库

其他的非关系数据库还有Memcached等

Memcached是一个分布式内存缓存系统, 适合用作缓存或会话存储

Redis是一个内存中的数据结构存储, 适合用作缓存, 数据库, 消息代理和队列等

Redis数据结构

Redis主要5种基本数据结构: String, Hash, List, Set, SortedSet

String/(Simple Dynamic String, SDS)

传统编程语言, 例如C, Java, Go等, 字符串String都是默认不可以更改的, Redis的字符串没有采用这种形式

Redis默认采用的是简单动态字符串SDS, 而传统数据结构种不可修改的字符串被Redis用作字符串字面量(string literal), 用在打印日志等无需对字符串值进行修改的场景下

Redis的SDS和Go的Slice很像, 设计理念几乎一致.

  • 和Slice一样, 维护了一个Capacity(free)和Length, 因此获取字符串长度时可以直接取Length达到O(1)的效率.
  • 和Slice一样, 申请空间时会预先申请略大的空间(Capacity), 当字符串/Slice增加时, 不需要额外申请空间, 可以直接为新元素分配已有的空间. 当减少长度时, 与Slice一样可以直接使用切片的方式减少空间
  • 会预先检查剩余空间, 避免缓存区溢出
 struct SDShdr {
   int len;
   int free;
   char buf[];
 };

与Slice不太一样的是, SDS使用free(剩余可使用空间)来维护容量

并且buf数组最后一位会默认保存'\0'表示终止

SDS剩余空间分配方式:

  1. 如果SDS修改后, SDS的len值小于1MB, 那么会为SDS分配和len值一样的未使用空间, 即free=len

  2. 如果SDS修改后, SDS的len值大于等于1MB, 那么默认为SDS分配1MB空间

  3. SDS的最大长度为512MB

    Go中的Slice空间分配方式

    1. 如果期望容量大于当前容量的两倍就会使用期望容量;

    2. 如果当前切片的长度小于 1024 就会将容量翻倍;

    3. 如果当前切片的长度大于 1024 就会每次增加 25% 的容量,直到新容量大于期望容量

      值得注意, 一次性append多个数据, go会预估新的容量

      另外, 需要考虑内存对齐对其的影响, 即需要考虑go内存分配中, object(mspan划分而成的小块)对其的影响,

      eg: 一次性append多个int值, slice预估大小为5, 所占空间为5*8B(int64大小), 而go中object的大小一般为8B, 16B, 32B, 48B, 64B, 80B, 96B, 112B.....最大为32KB.

     //runtime.growslice扩容代码
         newcap := old.cap
         doublecap := newcap + newcap
         if cap > doublecap {
             newcap = cap
         } else {
             if old.len < 1024 {
                 newcap = doublecap
             } else {
                 // Check 0 < newcap to detect overflow
                 // and prevent an infinite loop.
                 for 0 < newcap && newcap < cap {
                     newcap += newcap / 4
                 }
                 // Set newcap to the requested cap when
                 // the newcap calculation overflowed.
                 if newcap <= 0 {
                     newcap = cap
                 }
             }
         }
    

参考链接

  1. 通俗易懂的Redis数据结构基础教程
  2. 《我们一起进大厂》系列- Redis基础
  3. Go slice扩容深度分析