redis的数据类型

Redis的五种基本数据类型:

  • string 字符串
  • list 列表 (简单的字符串列表)
  • hash 哈希
  • set 集合 (string类型的无序集合)
  • zset 有序集合 (string类型的有序集合)

也可以理解为Redis五种类型的对象:
字符串对象、列表对象、哈希对象、集合对象、有序集合对象

Redis的基本数据结构:

  • sds简单动态字符串
  • 链表
  • 字典(符号表)
  • 跳跃表
  • intset整数集合
  • ziplist压缩列表
sds简单动态字符串
struct sdshdfr {
	// 记录buf数组中一十一字节的数量
	// 等于 SDS所保存字符串的长度
	int len;
	
	// 记录buff数组未使用字节的长度
	int free;
	
	// 字节数组,用于保存字符串
	char buf[];
}'\0'结尾,'\0'不包括在len里

与普通字符串的区别:

  • 获取字符串长度 为常数系复杂度
  • 杜绝缓冲区溢出
  • 减少修改字符串时带来的内存重分配次数
  • 二进制安全
链表
typedef struct listNode {

    // 前置节点
    struct listNode *prev;

    // 后置节点
    struct listNode *next;

    // 节点的值
    void *value;

} listNode;

/*
 * 双端链表结构
 */
typedef struct list {

    // 表头节点
    listNode *head;

    // 表尾节点
    listNode *tail;

    // 节点值复制函数
    void *(*dup)(void *ptr);

    // 节点值释放函数
    void (*free)(void *ptr);

    // 节点值对比函数
    int (*match)(void *ptr, void *key);

    // 链表所包含的节点数量
    unsigned long len;

} list;

Redis的链表实现的特性:

  • 双端队列
  • 无环:head.prev 和 tail.next 都指向NULL,对链表的访问以NULL为终点。
  • 带表头指针 head 和表尾指针 tail
  • 带链表长度 len
  • 多态:链表节点用void*指针来保存节点值
字典(符号表)
/*
 * 哈希表
 *
 * 每个字典都使用两个哈希表,从而实现渐进式 rehash 。
 */
typedef struct dictht {
    
    // 哈希表数组
    dictEntry **table;

    // 哈希表大小
    unsigned long size;
    
    // 哈希表大小掩码,用于计算索引值
    // 总是等于 size - 1
    unsigned long sizemask;

    // 该哈希表已有节点的数量
    unsigned long used;

} dictht;


/*
 * 哈希表节点
 */
typedef struct dictEntry {
    
    // 键
    void *key;

    // 值
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
    } v;

    // 指向下个哈希表节点,形成链表
    struct dictEntry *next;

} dictEntry;


/*
 * 字典
 */
typedef struct dict {

    // 类型特定函数
    dictType *type;

    // 私有数据
    void *privdata;

    // 哈希表
    dictht ht[2];

    // rehash 索引
    // 当 rehash 不在进行时,值为 -1
    int rehashidx; /* rehashing not in progress if rehashidx == -1 */

    // 目前正在运行的安全迭代器的数量
    int iterators; /* number of iterators currently running */

} dict;

  • 用链地址法解决冲突
  • 渐进式 rehash
intset整数集合
typedef struct intset {
    
    // 编码方式
    uint32_t encoding;

    // 集合包含的元素数量
    uint32_t length;

    // 保存元素的数组
    int8_t contents[];

} intset;
  • 整数集合的每个元素都是contents数组的一个数组项(item),各个项在数组中按值的大小从小到大有序的排列,并且数组中不包括任何重复项。
  • 在有需要时,程序会根据新添加元素的类型,改变这个数组的类型。
压缩列表zipList

当一个列表键只包含少量列表项,并且每个列表项要么时小的整数,要么就是长度较短的字符串时,那么Redis就会使用压缩列表来做列表键的底层实现。

skipList跳跃表
public class IntSkipList {

    private class Node {
        public Node[] next;
        public int value;

        public Node(int value, int level) {
            this.value = value;
            this.next = new Node[level];
        }
    }

    private Node _head = new Node(0, 33);
    private Random _random = new Random();
    private int _levels = 1;

    public void insert(int value) {
        // Determine the level of the new node. Generate a random number R. The number of
        // 1-bits before we encounter the first 0-bit is the level of the node. Since R is
        // 32-bit, the level can be at most 32.

        int level = 0;
        //(r & 1) == 1表示r为奇数  50%
        for (int r = _random.nextInt(); (r & 1) == 1; r >>= 1) {
            level++;
            if (level == _levels) {
                _levels++;
                break;
            }
        }

        // Insert this node into the skip list
        Node newNode = new Node(value, level + 1);
        Node cur = _head;

        for (int i = _levels - 1; i >= 0; i--) {
            for (; cur.next[i] != null; cur = cur.next[i]) {
                if (cur.next[i].value > value) {
                    break;
                }

                if (i <= level) {
                    newNode.next[i] = cur.next[i];
                    cur.next[i] = newNode;
                }
            }
         }
    }

    public boolean contains(int value) {
        Node cur = _head;

        for (int i = _levels - 1; i >= 0; i--) {
            for (; cur.next[i] != null; cur = cur.next[i]) {
                if (cur.next[i].value > value) {
                    break;
                }

                if (cur.next[i].value == value) {
                    return true;
                }
            }
        }

        return false;
    }

    public boolean remove(int value) {
        Node cur = _head;
        boolean found = false;

        for (int i = _levels - 1; i >= 0; i--) {
            for (; cur.next[i] != null; cur = cur.next[i]) {
                if (cur.next[i].value == value) {
                    found = true;
                    cur.next[i] = cur.next[i].next[i];
                    break;
                }

                if (cur.next[i].value > value) {
                    break;
                }
            }
        }
        return found;
    }

//    public int randomLevel(double p) {
//        int newLevel = 1;
//
//        while (Math.random() < p) {
//            newLevel++;
//        }
//
//        return Math.min(newLevel, MaxLevel);
//    }

}

跳跃表
Operation			Time Complexity
Insertion			O(log N)
Removal				O(log N)
Check if contains	O(log N)
Enumerate in order	O(N)

单链表
Operation			Time Complexity
Insertion			O(N)
Removal				O(N)
Check if contains	O(N)
Enumerate in order	O(N)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值