redis五种主要数据类型:
reidis 是key-value的方式存储,其中key和value在redis里都被称为对象,而value支持丰富的对象种类,其中有五种最为主要的数据类型分别是String,List,Set,Hash,sorted Set,只要掌握了这五种数据类型那么redis的基础也就掌握了。
String:
基本操作:
//获取值
get key
//获取多个值
mget key1,key2
//创建键值对并设置过期时间为second秒
set key value EX second
px millisecond//过期时间为millisecond毫秒
//创建键值对并只有当键不存在时才创建
set key value NX
//创建键值对并只有当键存在的时候才创建
set key value XX
编码方式:
String对象的编码方式有EMBSTR,RAW,INT,当数据为long以内的整型,redis默认使用INT的编码方式,当字符串小于阈值字节(现有的版本是44个字节)使用 EMBSTR的编码方式,大于后使用RAW的编码方式,RAW和EMBSTR不同的点在于前一种是数据对象和SDS是分开放的,而EMBSTR是放置在同一块内存区域
PS:SDS是redis针对以前C字符串中存在的缺点(字符串长度是遍历得到的而且还有一个‘\0'字符占用内存)设计出的一种新的数据结构,主要是alloc(存储当前已经分配了多少内存),len(记录字符串长度),buff(字符串数组)
List:
基本操作:
// 添加元素到列表
LPUSH key value [value ...]
RPUSH key value [value ...]
// 从列表中移除元素
LPOP key
RPOP key
// 获取列表长度
LLEN key
// 获取列表指定范围内的元素
LRANGE key start stop
// 设置列表指定位置的元素值
LSET key index value
// 通过索引获取列表中的元素
LINDEX key index
// 移除列表中等于 value 的元素
LREM key count value
// 将一个列表的元素移动到另一个列表
RPOPLPUSH source destination
// 截断列表,只保留指定范围内的元素
LTRIM key start stop
编码方式:
list的底层编码方式有ZIPLIST和LINKLIST可以类比java中的ArrayList和LinkedList,它们在内存中存储方式有如下区别:
但是呢,linklist比较占内存(内存碎片产生),ziplist在插入数据的时候又会进行多次复制移位
于是redis把他俩合体了:
每个节点是一个ziplist
Set:
基本操作:
添加元素:
SADD key member [member ...]
移除元素:
SREM key member [member ...]
检查元素是否存在:
SISMEMBER key member
获取集合中的所有元素:
SMEMBERS key
获取集合的基数(元素个数):
SCARD key
随机返回集合中的元素:
SRANDMEMBER key [count]
集合的交集:
SINTER key [key ...]
集合的并集:
SUNION key [key ...]
集合的差集:
SDIFF key [key ...]
将交集存储到另一个集合:
SINTERSTORE destination key [key ...]
将并集存储到另一个集合:
SUNIONSTORE destination key [key ...]
将差集存储到另一个集合:
SDIFFSTORE destination key [key ...]
删除集合:
DEL key
编码方式:
主要有INTSET和Hashtable,当元素小于512时会使用INTSET因为其内存连续节约内存,不过查询时使用的是二分查询,当元素大于512时就会转为hashtable,其查询效率很高为O(1)
Hash:
基本操作:
创建和修改哈希:
HSET key field value
HSETNX key field value
获取哈希中的值:
HGET key field
HGETALL key
删除哈希中的字段:
HDEL key field [field ...]
检查哈希中的字段是否存在:
HEXISTS key field
获取哈希中的所有字段:
HKEYS key
获取哈希中的所有值:
HVALS key
获取哈希中的字段和值:
HSCAN key cursor [MATCH pattern] [COUNT count]
获取哈希中的字段数量:
HLEN key
增量操作:
HINCRBY key field increment
HINCRBYFLOAT key field increment
删除哈希:
DEL key
编码方式:
编码方式是ziplist和hashtable,当值和键长度都小于64字节,元素个数小于512个的时候使用ziplist, 不同时满足以上两个条件时使用hashtable
在ziplist中存储时是直接以键键值对的方式存储,前一个元素是键,后一个元素就是值:
Zset:
基本操作:
添加成员:
ZADD key score member [score member ...]
获取成员分数:
ZSCORE key member
获取指定范围内的成员:
ZRANGE key start stop [WITHSCORES]
ZREVRANGE key start stop [WITHSCORES]
获取指定分数范围内的成员:
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
删除成员:
ZREM key member [member ...]
ZREMRANGEBYRANK key start stop
ZREMRANGEBYSCORE key min max
获取成员排名:
ZRANK key member
ZREVRANK key member
获取有序集合的基数:
ZCARD key
获取有序集合的分数区间:
ZCOUNT key min max
获取有序集合的总分和:
ZSUM key
删除有序集合:
DEL key
编码方式:
如果元素个数小于128个,字符串长度小于64字节就默认使用ziplist,否则就使用skiplist+hashtable的方式
ZIPLIST
结构图:
特性:
由于有Zltail故其可以双向遍历
Zllen是两个字节的也就是说当长度超过了65535(2^16-1)时就会遍历计数,时间复杂度为O(n),其它情况下就是O(1)
连锁更新的问题,由于ziplist中每一个data中的数据还存储了一个pre_len的字段,用于从后向前遍历,如果前面数据占据的字节超过了两个字节,那么后面data的pre_len就会又多出字节,后面的也都会跟着连锁更新,所以后面使用listpack进行优化,将原本记录前一个节点的pre_len换为了e'lement-tot-len只记录本节点除这个字段之外的长度
SKIPLIST
结构图:
插入过程:
当35要插入时走二级索引 比42小那么就回退到一级索引30处将其插入
特性:
redis里的跳表score是可以重复的
在插入元素时使用概率均衡的思想来决定插入元素的层数,是否能增加一层的概率为25%
性能方面平均下来是O(logN)
HASHTABLE
结构图:
扩容
缩容操作就是新建一个比新表小一倍的按照渐进式进行缩容