深入了解 RedisRedis 数据类型及操作
Posted 思想累积
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入了解 RedisRedis 数据类型及操作相关的知识,希望对你有一定的参考价值。
1、Redis 数据类型
Redis 单线程快的原因
高性能服务器不一定是多线程的
多线程 CPU 会上下文切换,比较耗时。
CPU - 内存 - 硬盘 的速度比较慢。
核心:Redis 将所有数据放在内存中,单线程操作效率很高,内存系统,没有上下问切换效率就是最高的。
redis官网地址
redis 命令参考
Redis-key
- Redis 的 redisObject 结构
typedef struct redisObject {
unsigned type:4; // 类型
unsigned encoding:4; // 编码
unsigned lru:LRU_BITS;
int refcount;
void *ptr; // 指向底层实现数据结构的指针
} robj;
encoding 记录了队形使用的编码,即对象底层使用的数据结构,我们存入 key-value 键值对并不会指定对象的 encoding,Redis 会根据不同场景设置不同的编码
编码常量 | 编码对应底层数据结构 | OBJECT_ENCODING 命令输出 |
---|---|---|
REDIS_ENCODING_INT | long 类型整数 | int |
REDIS_ENCODING_EMBSTR | embstr 编码的简单动态字符串 | embstr |
REDIS_ENCODING_RAW | 简单动态字符串 | raw |
REDIS_ENCODING_HT | 字典 | hashtable |
REDIS_ENCODING_LINKEDLIST | 双端链表 | linkedlist |
REDIS_ENCODING_ZIPLIST | 压缩列表 | ziplist |
REDIS_ENCODING_INTSET | 整数集合 | intset |
REDIS_ENCODING_SKIPLIST | 跳跃表和字典 | skiplist |
1.1 String(字符串)
数据结构:
struct sdshdr{
int len;
int free;
char buf[];
}
常用命令:
127.0.0.1:6379> set key v1 # 设置值
OK
127.0.0.1:6379> get key # 获得值
"v1"
127.0.0.1:6379> keys * # 所有的 key
"key"
127.0.0.1:6379> exists key # 判断某个 key 是否存在
(integer) 1
127.0.0.1:6379> append key va2 # 追加字符串,如果不存在,相当于 setkey
(integer) 5
127.0.0.1:6379> get key
"v1va2"
127.0.0.1:6379> append key "key1"
(integer) 9
127.0.0.1:6379> get key
"v1va2key1"
127.0.0.1:6379> strlen key # 获取字符串长度
(integer) 9
127.0.0.1:6379> append key ,,,
(integer) 12
127.0.0.1:6379> get key
"v1va2key1,,,"
127.0.0.1:6379> strlen key
(integer) 12
127.0.0.1:6379> append name zhangsan
(integer) 8
127.0.0.1:6379> get name
"zhangsan"
###########################################
# i ++
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> type views
string
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views # 增加 1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> decr views # 减少 1
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> incrby views 10 # 增加 10
(integer) 11
127.0.0.1:6379> get views
"11"
127.0.0.1:6379> decrby views 5 # 减少 5
(integer) 6
127.0.0.1:6379> get views
"6"
###########################################
# 字符串范围
127.0.0.1:6379> keys *
1) "key"
127.0.0.1:6379> set key "hello,word" # 设置字符串
OK
127.0.0.1:6379> get key
"hello,word"
127.0.0.1:6379> getrange key 0 3 # 截取字符串 [0,3]
"hell"
127.0.0.1:6379> getrange key 0 -1 # 截取全部字符串,相当于 get key
"hello,word"
# 替换字符串
127.0.0.1:6379> set key1 abdfsa
OK
127.0.0.1:6379> get key1
"abdfsa"
127.0.0.1:6379> setrange key1 1 sss # 替换指定位置开始字符串
(integer) 6
127.0.0.1:6379> getrange key1 0 -1
"assssa"
###########################################
# setex (set with expire) # 设置过期时间
# setnx (set if not exist) # 不存在再设置 (在分布式锁中使用)
127.0.0.1:6379> setex key2 30 "hello" # 设置 key2 的值为 hello 30秒后过期
OK
127.0.0.1:6379> ttl key3
(integer) -2
127.0.0.1:6379> setex key2 30 "hello"
OK
127.0.0.1:6379> ttl key2
(integer) 25
127.0.0.1:6379> setnx mykey "redis" # 如果 mykey 不存在,创建 mykey
(integer) 1
127.0.0.1:6379> keys *
1) "key2"
2) "key1"
3) "key"
4) "mykey"
127.0.0.1:6379> ttl key2
(integer) 1
127.0.0.1:6379> keys *
1) "key1"
2) "key"
3) "mykey"
127.0.0.1:6379> setnx mykey "MongoDB" # 如果 mykey 存在,创建失败!
(integer) 0
127.0.0.1:6379> get mykey
"redis"
###########################################
# mset
# mget
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 同时设置多个值
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"
127.0.0.1:6379> mget k1 k2 k3 # 同时获取多个值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v1 k4 v4 # msetnx 是一个 原子性操作!
(integer) 0
127.0.0.1:6379> get k4
(nil)
# 对象
set user:1 {name:zhangsan,age:3} # 设置一个 user:1 对象,值为 json 字符来保存一个对象
# 这里的 key 为 user:{id}:{name}
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "2"
###########################################
# getset # 先 get 再 set
127.0.0.1:6379> getset db redis # 如果不存在,返回 nil
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db MongoDB # 如果存在值,获取原来的值,设置新的值。
"redis"
127.0.0.1:6379> get db
"MongoDB"
应用场景:
普通的 key/value 存储。
统计多单位的数量
粉丝数
分布式锁
计数器
分布式 session
对象缓存
1.2 List ( 列表 )
list 可以作为栈,队列,阻塞队列!
list 命令已 l 开头
常用命令:
###########################################
127.0.0.1:6379> lpush list one # 头插法,将一个或多个值插入列表头部
(integer) 1
127.0.0.1:6379> lpush list tow
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1 # 获取 list 中的值
1) "three"
2) "tow"
3) "one"
127.0.0.1:6379> rpush list four # 尾插法,将一个或多个值插入到列表尾部
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "tow"
3) "one"
4) "four"
###########################################
# lpop
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "tow"
3) "one"
4) "four"
127.0.0.1:6379> lpop list # 移除列表第一个元素
"three"
127.0.0.1:6379> rpop list # 移除列表最后一个元素
"four"
127.0.0.1:6379> lrange list 0 -1
1) "tow"
2) "one"
###########################################
# lindex
127.0.0.1:6379> lrange list 0 -1
1) "tow"
2) "one"
127.0.0.1:6379> lindex list 0 # 通过下标获取 list 中的值.
"tow"
127.0.0.1:6379> lindex list 1
"one"
###########################################
# llen
127.0.0.1:6379> llen list # 返回列表长度
(integer) 2
###########################################
# 移除指定的值 # lrem
127.0.0.1:6379> lrange list 0 -1
1) "tow"
2) "one"
127.0.0.1:6379> lrem list 1 one # 移除 list 集合中指定个数的 value,精确匹配
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "tow"
127.0.0.1:6379> lpush list tow
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "tow"
3) "tow"
127.0.0.1:6379> lrem list 2 three
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "tow"
2) "tow"
###########################################
# trim list 截取
127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> RPUSH mylist "hello1"
(integer) 2
127.0.0.1:6379> rpush mylist "hello2"
(integer) 3
127.0.0.1:6379> rpush mylist "hello4"
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello4"
127.0.0.1:6379> ltrim mylist 1 2 # 通过下标截取指定位置元素
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
###########################################
# rpoplpush # 移除列表尾部元素并添加到新列表中
127.0.0.1:6379> rpush mylist "hel1o"
(integer) 1
127.0.0.1:6379> rpush mylist "hello1"
(integer) 2
127.0.0.1:6379> rpush mylist "hello2"
(integer) 3
127.0.0.1:6379> rpoplpush mylist otherlist # 移除列表尾部元素并添加到新列表中
"hello2"
127.0.0.1:6379> lrange mylist 0 -1 # 原来列表
1) "hel1o"
2) "hello1"
127.0.0.1:6379> lrange otherlist 0 -1 # 目标列表
1) "hello2"
###########################################
# 列表中指定下标的值替换为另外的值,更新操作
127.0.0.1:6379> exists list # 判断列表是否存在
(integer) 0
127.0.0.1:6379> lset list 0 item # 不存在就会报错
(error) ERR no such key
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 item # 如果存在更新下标的值
OK
127.0.0.1:6379> lrange list 0 0
1) "item"
127.0.0.1:6379> lset list 1 item2 # 不存在就会报错
(error) ERR index out of range
###########################################
# linsert # 将某个具体的具体的 value 值插入列表中
127.0.0.1:6379> rpush list hello
(integer) 1
127.0.0.1:6379> rpush list word
(integer) 2
127.0.0.1:6379> linsert list before word other # 插入到指定值之前
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "other"
3) "word"
127.0.0.1:6379> linsert list after word new
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "other"
3) "word"
4) "new"
- list 是一个链表,before,after,left,right 都可以插入值
- 如果 key 不存在,创建新的链表
- 如果 key 存在,新增内容
- 如果移除了所有值,空链表,不存在
- 在两边插入或者改动值,效率最高。
应用场景:
消息队列 Stack = LPUSH + LPOP
栈 Queue = LPUSH + RPOP
Blocking MQ = LPUSH + BRPOP
消息流
1.3 hash ( 哈希 )
Map 集合,key - map 集合,本质和 string 类型没有太大区别,是简单的 key - value
常用命令:
###########################################
127.0.0.1:6379> hset hash 1 2 # set 一个具体的 key - value
(integer) 1
127.0.0.1:6379> hset hash key1 value1
(integer) 1
127.0.0.1:6379> hget hash key1 # 获取 指定 key 的值
"value1"
127.0.0.1:6379> hmset hash key value key2 value2 # set 多个 key - value
OK
127.0.0.1:6379> hmget hash key 1 key2 # get 多个字段值
1) "value"
2) "2"
3) "value2"
127.0.0.1:6379> hgetall hash # 获取所有 key - value 数据
1) "1"
2) "2"
3) "key1"
4) "value1"
5) "key"
6) "value"
7) "key2"
8) "value2"
###########################################
127.0.0.1:6379> hdel hash 1 # 删除指定 key 的 value
(integer) 1
127.0.0.1:6379> hgetall hash
1) "key1"
2) "value1"
3) "key"
4) "value"
5) "key2"
6) "value2"
###########################################
127.0.0.1:6379> hlen hash # 获取 hash 表的字段数量
(integer) 3
127.0.0.1:6379> hmset hash hello word
OK
127.0.0.1:6379> hgetall hash
1) "key1"
2) "value1"
3) "key"
4) "value"
5) "key2"
6) "value2"
7) "hello"
8) "word"
###########################################
127.0.0.1:6379> HEXISTS hash key1 # 判断 hash 中的指定字段是否存在
(integer) 1
127.0.0.1:6379> hexists hash key3
(integer) 0
###########################################
127.0.0.1:6379> hkeys hash # 只获得所有的 key
1) "key1"
2) "key"
3) "key2"
4) "hello"
127.0.0.1:6379> hvals hash # 只获得所有的 value
1) "value1"
2) "value"
3) "value2"
4) "word"
###########################################
127.0.0.1:6379> hset hash star 5
(integer) 1
127.0.0.1:6379> hget hash star
"5"
127.0.0.1:6379> HINCRBY hash star 1 # 指定增量 1
(integer) 6
127.0.0.1:6379> HINCRBY hash star -1
(integer) 5
127.0.0.1:6379> hsetnx hash value3 hello # 如果不存在可以设置
(integer) 1
127.0.0.1:6379> hsetnx hash value3 word # 存在则不能设置
(integer) 0
应用场景:
变更数据,用户信息保存,经常变动的信息,适合对象存储
购物车
1.4 set ( 集合 )
set 中的值不能重复
常用命令:
###########################################
127.0.0.1:6379> sadd set hello # set 集合中添加元素
(integer) 1
127.0.0.1:6379> sadd set hello1
(integer) 1
127.0.0.1:6379> sadd set hello2
(integer) 1
127.0.0.1:6379> SMEMBERS set # 查看指定 set 的所有值
1) "hello2"
2) "hello1"
3) "hello"
127.0.0.1:6379> SISMEMBER set hello # 查看某个值是否在 set 集合中,存在为 1,不存在为 0
(integer) 1
127.0.0.1:6379> SISMEMBER set word
(integer) 0
###########################################
127.0.0.1:6379> scard set # 获取 set 集合中的元素个数
(integer) 3
127.0.0.1:6379> sadd set hello
(integer) 0
127.0.0.1:6379> sadd set hello3
(integer) 1
127.0.0.1:6379> scard set
(integer) 4
###########################################
127.0.0.1:6379> srem set hello # 移除某个元素
(integer) 1
127.0.0.1:6379> scard set
(integer) 3
127.0.0.1:6379> SMEMBERS set
1) "hello2"
2) "hello1"
3) "hello3"
###########################################
127.0.0.1:6379> SRANDMEMBER set # 随机抽取一个元素
"hello1"
127.0.0.1:6379> SRANDMEMBER set
"hello3"
127.0.0.1:6379> SRANDMEMBER set
"hello2"
127.0.0.1:6379> SRANDMEMBER set
"hello3"
127.0.0.1:6379> srandmember set 2 # 随机抽取指定个数元素
1) "hello1"
2) "hello2"
###########################################
# 删除指定的 key,删除随机的 key
127.0.0.1:6379> spop set # 随机删除一些 set 集合中的元素
"hello3"
127.0.0.1:6379> spop set
"hello2"
127.0.0.1:6379> SMEMBERS set
1) "hello1"
127.0.0.1:6379> SMEMBERS set
1) "hello1"
###########################################
# 一个指定的值,移动到另外一个集合中。
127.0.0.1:6379> sadd set hello
(integer) 1
127.0.0.1:6379> sadd set hello1
(integer) 1
127.0.0.1:6379> sadd set hello2
(integer) 1
127.0.0.1:6379> sadd set hello3
(integer) 1
127.0.0.1:6379> sadd set2 hello
(integer) 1
127.0.0.1:6379> smove set set2 hello1 # # 一个指定的值,移动到另外一个集合中。
(integer) 1
127.0.0.1:6379> SMEMBERS set2
1) "hello1"
2) "hello"
###########################################
# 交集,差集,并集以上是关于深入了解 RedisRedis 数据类型及操作的主要内容,如果未能解决你的问题,请参考以下文章
redis数据库简介redis下载及安装(win64位)node操作redisredis实现短信校验注册接口