Redis的Key永远都是string类型,nil代表null
具体的底层实现原理可以参考书籍《Redis设计与实现》
Value的五种常用数据类型
类型 | 类似于Java的 |
---|---|
string | String |
hash | HashMap |
list | LinkedList |
set | HashSet |
sorted_set | TreeSet |
1 string类型
最常用也最简单的数据存储类型,一个存储空间保存一个数据。整数字符串可以作为数字操作使用。
底层实现
每个string类型的结构如下:
struct sdshdr{
// 记录buf数组中已使用字节的数量等于SD所保存字符串的长度
int len;
// 记录buf数组中未使用字节的数量
int free;
// 字节数组,用于保存字符串
char buf[];
}
基本操作
操作 | 格式 |
---|---|
添加/修改数据 | set key value |
添加修改多个数据 | mset key1 value1 key2 value2 |
获取数据 | get key |
获取多个数据 | mget key1 key2 |
删除数据(返回integer 1或者0) | del key |
获取数据字符个数(string的length) | strlen key |
追加信息到字符串后面(没有就新建,返回length值) | append key value |
set和mset要因地制宜的使用,并没有哪个更好的道理。
string类型数字数据的拓展操作
1.给数字字符串数据增加值
指令 | 说明 |
---|---|
incr key | +1 |
incrby key increment | +指定的值(只能为整数) |
incrbyfloat key increment | +指定的小数的值 |
2.给数字字符串减少值
指令 | 说明 |
---|---|
decr key | -1 |
decrby key increment | 不说了 |
注意:数字类型最大等同于Java的Long.MAX_VALUE
数据时效性设置
指令 | 说明 |
---|---|
setex key seconds value | 设置某个key的生命周期为指定秒 |
psetex key milliseconds value | 指定毫秒 |
key的设置约定
数据库中的key命名惯例:
表名:主键名:主键值:字段名
2 Redis hash类型
一个存储空间保存多个键值对数据,底层使用哈希表结构实现数据存储
hash存储结构优化
- 如果field数量较少,存储结构优化为类数组结构
- 如果field数量较多,存储结构使用HashMap结构
key -> { field1 : value1
field2 : value2
field3 : value3
...
}
基本操作
操作 | 说明 |
---|---|
hset key field value | 添加和修改数据 |
hget key field | 获取数据 |
hgetall key | 按key获取所有数据 |
hdel key field1 [field2] | 删除数据 |
hmset key field1 value1 field2 value2 | 添加和修改多个数据 |
hmget key field1 field2 ... | get多个数据 |
hlen key | 获取哈希表中field-value的数量 |
hexists key field | 获取哈希表中是否存在指定的字段 |
拓展操作
操作 | 说明 |
---|---|
hkeys key | 获取key中的所有field |
hvals key | 获取key中的所有value |
hincrby key field increment | 按值增加value数值 |
hincrybyfloat key field increment | 还是增加(小数OK) |
注意事项
- hash类型下的value只能存储string类型,不能嵌套一个hash什么的
- 如果没获取到对应的值为nil
- 每个hash可以存储2^32-1个键值对
hgetall
如果内部field过多,则效率会很低(为啥呢?),可能成为数据访问瓶颈
应用场景举例
电商网站购物车的设计与实现(简单版)
- key:用户id
- field:商品id和数量以及各种其他的信息
- value:商品购买数量
实现操作
- 添加商品:增加全新的field和value
- 游览购物车:遍历hash
- 更改数量:自增/自减,设置value值
- 删除商品:删除field
- 清空:删除key
例如:
g01:nums 100 g01:info{json表单} ...
拓展操作:
hsetnx key field value
添加前判断是否已经存在field,如果存在则不添加,不存在则添加
3 list类型
特点
- 底层使用带头尾指针的无环双向链表
- 带链表长度计数器
unsigned long len
- 链表可以保存各种不同类型的值
- 头尾指针都指向null,对链表的访问以null为终点
底层实现
每一个链表结点的定义如下:
typedef struct listNode{
//前置节点
struct listNode *prev;
//后置节点
struct listNode *next;
//节点的值
void *value;
}listNode;
每个链表的定义如下:
typedef struct list{
//表头节点
listNode *head;
//表尾结点
listNode *tail;
//链表所包含的节点数量
unsigned long len;
//节点值赋值函数
void *(*dup) (void *ptr);
//节点值释放函数
void (*free) (void *ptr);
//节点值对比函数
int (*match) (void *ptr,void *key);
} list;
基本操作
操作 | 说明 |
---|---|
lpush key value1 [value2] ... | 从左边插入新节点 |
rpush key value1 [value2]... | 从右边插入新节点 |
lrange key start stop | 按索引范围获取 |
lindex key index | 按索引获取 |
llen key | 获取长度 |
lpop key | 删除最左的节点 |
rpop key | 删除最右的节点 |
拓展操作
操作 | 说明 |
---|---|
blpop key [key2] timeout | 等待timeout秒数之后,直到能从左边pop出来key(block left pop) |
brpop key [key2] timeout | 等待指定秒数,直到能从右边取出 |
lrem key count value | 从左边数删除count个指定的value |
注意事项
- list节点量最大为2^32-1个元素
- 可以按索引取数,但一般用pop方式取数(毕竟时间复杂度低)
- 可以实现对数据进行分页操作
4 set类型
存储需求:存储大量的数据,并且能够提供高效率的查询
特点:
- 对应的hash存储结构中只有key,没有value(value为nil)
- Redis里面的value就是set类型的key
- 因为索引不能重名,所以value是不可以重复的(不会覆盖,直接不允许)
- 可以应用于同类数据的自动快速去重添加、自动制作黑白名单等
基本操作
操作 | 说明 |
---|---|
sadd key member1 [member2] | 添加数据 |
smembers key | 获取全部数据 |
srem key member1 [member2] | 删除数据 |
scard key | 获取集合数据总量 |
sismember key member | 判断是否存在指定数据 |
拓展操作
操作 | 说明 |
---|---|
srandmember key [count] | 随机从key中取一个(或者几个)数据 |
spop key | 随机获取一个并且移除 |
集合相关操作
操作 | 说明 |
---|---|
sinter key1 [key2] | 求并集 |
sunion key1 [key2] | 求交集 |
sdiff key1 [key2] | 求差集 |
sinterstore destination key [key2] | 求并集并存到新的集合中 |
sunionsotre , sdiffsotre | 同理 |
smove source destination member | 把member从指定集合移到另一个集合中 |
5 sorted_set类型
底层结构
在set的存储结构基础上添加可排序字段来实现(字典)
结构:
hash: key : value
sorted_set: value: 排序字段
set: value: (nil)
基本操作
操作 | 说明 |
---|---|
zadd key score1 member1 | 添加数据,score为排序字段,member为值 |
zrange key start stop [withscores] | 按索引起始获取全部数据[顺带score一起输出] |
zrevrange key start stop [withscores] | 和上面相比为按score降序输出 |
zrem key member | 删除数据 |
zrangebyscore key min max [withscores] [limit] | 按条件查询,(limit后面接个数范围) |
zrevrangebyscore key max min [withscores] | 按条件查询逆序输出 |
zremrangebyrank key start stop | 按索引删除 |
zremrangebyscore key min max | 按排序顺序删除 |
集合相关操作
操作 | 说明 |
---|---|
zcard key | 获取集合数据总量 |
zcount key min max | 获取指定大小区间的数据总量 |
zinterstore destination numkeys key | 求交集并存入destination |
zunionstore destination numkeys key | 求并集并存入destination |
拓展操作
操作 | 说明 |
---|---|
zrank key member | 升序输出排名 |
zrevrank key member | 降序输出排名 |
zscore key member | 输出score值 |
zincrby key increment member | 给指定member的score值+1 |
注意事项
- score保存的数据存储空间为64位
- score可以为双精度的double值(可能会丢失精度)
- sorted_set底层存储还是基于set结构的,因此数据不能重复,如果重复了key,则会覆盖掉score