目录
redis 的数据结构
常用数据类型的编码
OBJECT ENCODING
redis 为什么快
redis 的专用指令
string
SET
FLUSHALL
GET
MSET
MGET
INCR
INCRBY
DECR
DECRBY
INCRFLOAT
APPEND
GETRANGE
SETRANGE
STRLEN
内部编码方式
hash
HSET
HGET
HDEUL
HEXIXTS
HKEYS
HVALS
HGETALL
HMHET
HLEN
HSETNX
HINCRBY
HINCRBYFLOAT
hash 的编码方式
Strings
Lists
Sets
Hashes
Sorted sets
Strems
Geospatial
Bimaps
Bitfields
Probabilistic
虽然目前的 redis 有十个数据类型,但是我们常用的只有5个
数据结构 | 内部编码 |
---|---|
raw | |
string | int |
embstr | |
hash | hashtable |
ziplist | |
list | linkedlist |
ziplist | |
set | hashtable |
inset | |
zset | skiplist |
ziplist |
string
raw:最基本字符串(底层就是一个char 数组)
int:就是整数
embstr:针对段字符串进行特殊优化
hash
hashtable:最基本的 hash 表
ziplist:压缩链表
list
linkedlist:链表
ziplist:压缩链表
从 redis 3.2 开始,引入了新的实现方式 quicklist,quicklist 兼容了linkedlist 和 zipist的优点
quicklist就是一个链表,每一个元素又是ziplist
set
hashtable:hash 表
inset:集合中存的都是整数
zset
skiplist:跳表
ziplist:
该命令可以查看 key 队列value 的编码
object encoding key
返回值是 value 的编码方式
127.0.0.1:6379> object encoding key1
"embstr"
127.0.0.1:6379> object encoding key2
"quicklist"
127.0.0.1:6379> object encoding key3
"hashtable"
127.0.0.1:6379> object encoding key4
"ziplist"
谈论 redis 为什么快,当然需要一个参照(mysql)
首先是因为 redis 是访问内存,而mysql访问的是硬盘
redis 的核心功能比 mysql 的核心功能简单
redis 是单线程,无需为线程竞争切换等浪费时间
其中redis 是单线程和它的操作有关,redis 的操作都是短平快,不需要占用太多的cup资源,所以可以使用单线程
redis 处理网络请求的时候使用的是 epoll 多路复用
redis 中的 string,直接就是按照二进制的方式存储的(不会做任何编码,存的什么去的就是什么)
string 可以存储很多数据类型,普通字符串、整数、JSON、xml、二进制数据(图片、视频、音频...)
设置一个 key 和 value ,value 为string 类型
SET key value [expiration EX second | PX millisecond] [NX | XX]
[]:表示可选项
EX:表示设置超时时间 单位秒
PX:表示设置超时时间 单位毫秒
NX:如果key 不存在才设置,key存在则不设置,返回nil
XX:如果key存在,才设置(相当于跟新key的value)如果key不存在,则不设置
为了方便SET 的使用,还有一些类似的命令
SETNX
SETEX
SETPX
在介绍下面的命令之前,先介绍一个命令
flushall 作用就是删除 redis 上所有的数据
set 插入一个数据
127.0.0.1:6379> set key1 1
OK
set 插入数据设时间
127.0.0.1:6379> set key2 2 ex 10
OK
127.0.0.1:6379> ttl key2
(integer) 7
set插入数据,没有 key 就插入
127.0.0.1:6379> set key3 3 NX
OK
set 插入数据,有数据才插入
127.0.0.1:6379> set key3 3.1415926
OK
127.0.0.1:6379> get key3
"3.1415926"
setex 插入数据
127.0.0.1:6379> setex key4 10 4
OK
127.0.0.1:6379> get key4
"4"
setnx 插入数据
127.0.0.1:6379> setnx key5 5
(integer) 1
get 返回对应 key 的value 主要就是返回 string 的value
GET key
查询 string 类型
127.0.0.1:6379> get key1
"1"
查询非 string 类型
127.0.0.1:6379> lpush key6 6 66 666 6666
(integer) 4
127.0.0.1:6379> get key6
(error) WRONGTYPE Operation against a key holding the wrong kind of value
mset设置多组 key value
MSET key value [key value ....]
设置多组 key value
127.0.0.1:6379> mset key1 1 ksy2 2 ksy3 3
OK
获取多组 key 对应的value
MGET key [key...]
获取多组 key
127.0.0.1:6379> mget key1 ksy2 ksy3
1) "1"
2) "2"
3) "3"
对 value 进行 + 1
INCR key
返回值是+1后的值
如果没有对应的 key 则认为 key 为 0,然后返回对0+1 后的值
value 必须是 64 位整数才可以
string 类型不可以使用该命令
超过 64 位整数也不可以使用该命令
浮点数不可以使用该命令
插入数据后自增
127.0.0.1:6379> set key1 100
OK
127.0.0.1:6379> get key1
"100"
127.0.0.1:6379> incr key1
(integer) 101
127.0.0.1:6379> get key1
"101"
对string 类型进行自增
127.0.0.1:6379> set key2 hello
OK
127.0.0.1:6379> get key2
"hello"
127.0.0.1:6379> incr key2
(error) ERR value is not an integer or out of range
对浮点类型自增
127.0.0.1:6379> set key3 1.1
OK
127.0.0.1:6379> get key3
"1.1"
127.0.0.1:6379> incr key3
(error) ERR value is not an integer or out of range
没有对应的key进行自增
127.0.0.1:6379> incr key4
(integer) 1
127.0.0.1:6379> get key4
"1"
对超出64位整数进行自增
127.0.0.1:6379> set key5 9999999999999999999999999
OK
127.0.0.1:6379> incr key5
(error) ERR value is not an integer or out of range
对key对应的value进行加N操作
INCRBY key N
返回值是加N后的值
还可以加负数
其余和incr基本一样
加N
127.0.0.1:6379> set key6 100
OK
127.0.0.1:6379> incrby key6 100
(integer) 200
127.0.0.1:6379> get key6
"200"
对该值加一个负数
127.0.0.1:6379> get key6
"200"
127.0.0.1:6379> incrby key6 -199
(integer) 1
127.0.0.1:6379> get key6
"1"
对 key 对应的value 进行减一
DECR key
decr 也是只能对64位整数进行操作
返回值还是对value减一后的值
设置一个key对key进行减一
127.0.0.1:6379> set key1 100
OK
127.0.0.1:6379> decr key1
(integer) 99
127.0.0.1:6379> get key1
"99"
对没有对应key的进行减一
127.0.0.1:6379> decr key2
(integer) -1
127.0.0.1:6379> get key2
"-1"
剩下的其实和incr 的条件都一样
decrby 同样是对 key进行减N
DECRBY key N
返回对key减N后的值
其余的条件也是和上面类似
对key减N
127.0.0.1:6379> set key3 100
OK
127.0.0.1:6379> decrby key3 99
(integer) 1
127.0.0.1:6379> get key3
"1"
其余和上面类似,下面就不演示了
对key对应的value进行加(或者减)一个浮点数
INCRFLOAT key float
返回值是对key加或者减后的值
限制条件和上面的也差不多,但是还可以对浮点数进行操作
对key进行加一个数
127.0.0.1:6379> set key1 10
OK
127.0.0.1:6379> incrbyfloat key1 1.9
"11.9"
127.0.0.1:6379> get key1
"11.9"
对key减一个数
127.0.0.1:6379> set key2 10
OK
127.0.0.1:6379> incrbyfloat key2 -0.5
"9.5"
127.0.0.1:6379> get key2
"9.5"
对没有对应key value 的进行操作当然也是从0开始计算
127.0.0.1:6379> incrbyfloat key -0.5
"-0.5"
对浮点数进行操作
127.0.0.1:6379> set key3 3.14
OK
127.0.0.1:6379> incrbyfloat key3 1.1
"4.24"
127.0.0.1:6379> get key3
"4.24"
其中字符串也可以进行一些操作
追加字符串
APPEND key
返回值是追加后字符串的长度(字节数)
操作的对象必须是字符串
如果没有对应的key value则向set一样的功能
对key追加字符串
127.0.0.1:6379> set key1 hello
OK
127.0.0.1:6379> append key1 world
(integer) 10
127.0.0.1:6379> get key1
"helloworld"
对没有对应的 key value 追加
127.0.0.1:6379> append key2 hello
(integer) 5
127.0.0.1:6379> get key2
"hello"
对key追加汉字,会返回多少
127.0.0.1:6379> append key3 中国
(integer) 6
查询 key3
127.0.0.1:6379> get key3
"\xe4\xb8\xad\xe5\x9b\xbd"
为什么会是这样?
我们前面说过 redis 是不会对数据进行编码的存储进去什么取出来就是什么,汉字在 Xshell 上默认就是 utf8 所以存储进是按照二进制存储的,但是取出来不翻译
如何让 redis 尝试翻译?
可以在启动客户端的时候可以加 --raw
[lxy@hecs-165234 ~]$ redis-cli --raw
127.0.0.1:6379> get key3
中国
获取字符串中的一部分,类似于 substring
getrange key start end
返回值是截取到的字符
其中 start 和 end 可以为负数
但是这里的负数表示的并不是下标,而是从倒数开始
这里的 start 和 end 是闭区间
截取一段字符串
127.0.0.1:6379> getrange key1 0 -1
helloworld
上面表示从第0个字符开始,到最后一个字符
还可以截取中文
127.0.0.1:6379> getrange key3 0 -1
中国
如果截取一部分呢?
127.0.0.1:6379> getrange key3 1 -2
¸
上面截取出来的并不认识,这是因为现在的客户端还是 raw 模式,但是这里截取了四个字节的数据,然后客户端翻译后就成了这样
setrange 修改一段字符串
setrange key offset value
返回值就是修改后的字符串
offset 表示偏移量,从偏移量开始修改
修改的字符串的个数由value 的size决定
修改一个key对于的value
127.0.0.1:6379> set key helloworld
OK
127.0.0.1:6379> setrange key 1 TTTT
(integer) 10
127.0.0.1:6379> get key
"hTTTTworld"
如果超出原本字符串长度那么就会全部覆盖
127.0.0.1:6379> set key1 china
OK
127.0.0.1:6379> setrange key1 1 CCCCCCCCCCCCCCCCCCCCCCCCCC
(integer) 27
127.0.0.1:6379> get key1
"cCCCCCCCCCCCCCCCCCCCCCCCCCC"
如果对没有对应 key 和 value
127.0.0.1:6379> setrange key3 1 hello
(integer) 6
127.0.0.1:6379> get key3
"\x00hello"
如果没有对应的 key 那么就会从偏偏移量开始将设置的value设置进去,在偏移量之前的则使用 /x00代替
返回字符串的长度
STRLEN key
返回值是字符串的长度,单位字节
如果对于不存在的 key 返回0
操作对象只能是string类型
插入数据,使用 strlen 查看
127.0.0.1:6379> set key1 helloworld
OK
127.0.0.1:6379> strlen key1
10
插入中文
127.0.0.1:6379> set key2 中国
OK
127.0.0.1:6379> strlen key2
6
查看不存在的 key
127.0.0.1:6379> strlen key3
0
查看其他类型
127.0.0.1:6379> lpush key3 111 222 333
3
127.0.0.1:6379> strlen key3
WRONGTYPE Operation against a key holding the wrong kind of value
int:64位的整型/8位的整数
embstr:短的字符串
raw:字符串
hash 里面存储的是键值对
redis 里面存储的也是键值对
所以为例区分 hash 和 redis 的键值对redis 使用的是 key-value 而 hash 使用的是 field-value
hset 可以设置多个 field-value
hset key field value [field value]
hset 的返回值是设置成功后个数的返回值
hset 一个 key 可以有多个 field-value
设置多个 field-value
127.0.0.1:6379> hset key1 f1 111 f2 222 f3 333
3
设置后也可以继续设置
127.0.0.1:6379> hset key1 f4 444
1
查看 key 和 field 对应的value
hget key field [field]
返回值是 key 和 field 对应的值
查看刚才设置入的值
127.0.0.1:6379> hget key1 f1
111
查看不存在的值
127.0.0.1:6379> hget key1 f5
不存在的值什么都没有
hdel 删除的是 field-value
hdel key field [field ...]
hdel 可以删除多个 field-value
hdel的返回值是删除成功的个数
这里注意 del 删除的是 key 而hdel 删除的是 field-value
删除一个 field-value
127.0.0.1:6379> hdel key1 f1
1
删除多个
127.0.0.1:6379> hdel key1 f2 f3
2
删除不存在
127.0.0.1:6379> hdel key1 f5
0
查看刚才删除的 field
127.0.0.1:6379> hget key1 f1
这里显示没有,说明 f1 已经被删除了
del 删除 key1
127.0.0.1:6379> del key1
1
判断 key-field 是否存在
hexists key field
返回值,存在则返回 1 不存在则返回 0
判断是否存在
127.0.0.1:6379> hexists key1 f1
(integer) 0
下面插入一个 f1 1,然后查询
127.0.0.1:6379> hset key1 f1 1
(integer) 1
127.0.0.1:6379> hexists key1 f1
(integer) 1
查看 hash 中所有的 field
hkeys key
返回值是 key 对应的所有的 field
如果不存在那么就返回空
查看 key
127.0.0.1:6379> hkeys key1
1) "f1"
2) "f2"
3) "f3"
查看不存在的 key
127.0.0.1:6379> hkeys kwy
(empty list or set)
返回key 中对应的所有的 value
hvals key
返回值是 key 中 每个 field 对应的 value
如果为空则返回空
查看 key
127.0.0.1:6379> hvals key1
1) "111"
2) "222"
3) "333"
查看不存在的值
127.0.0.1:6379> hvals key
(empty list or set)
获取所有的 key 中的 field 和 value
hgetall key
返回值就是field 和 value 其中一条 field 下面是对应的 value
如果没有返回空
查看 key
127.0.0.1:6379> hgetall key1
f1
111
f2
222
f3
333
查看不存在的 key
127.0.0.1:6379> hgetall key
但是这个空是什么都没有,而不是报错。
上面的 hgetall 是将 key 里面对应的 field 和 value 统统返回,但是在线上环境的话这样左是比较危险的,所以还有一个命令是返回指定个数的 field 和 value
返回指定的 field 和 value
hmget key field [field ...]
返回值是field 对应的 value
如果不存在返回空
查看 key-field
127.0.0.1:6379> hmget key1 f1 f2 f3
111
222
333
查看不存在的值
127.0.0.1:6379> hmget key1 f1 2 3
111
其中 f1 是存在的 2 和 3 都不存在
返回 key 中对应的 hash 的个数
hlen key
返回值是 key 中对应的hash的个数
不存在则返回0
查看 key 里面 hash 的个数
127.0.0.1:6379> hlen key1
3
看到这个命令其实就猜到了其实个setnx差不多
这个命令也是不存在则设置,存在则设置失败
hsetnx key field value
返回值是,如果设置成功则返回 1,失败则返回 0
设置重复值
127.0.0.1:6379> hsetnx key1 f1 111
0
设置不重复的值
127.0.0.1:6379> hsetnx key1 f4 444
1
其实看到这个我们也可以想起 incrby
该命令就是对 field 对应的value进行加一个值
hincrby key field increment
返回值就是增加后的 value 的值
如果没有对应的那么就默认是以0开始
当然也可以加一个负数
对其中一个 key0field 增加一个值
127.0.0.1:6379> hincrby key1 f1 100
211
对一个不存在的增加一个值
127.0.0.1:6379> hincrby key1 f5 1
1
对一个 key-field 对应的value增加一个浮点数
hincrbyfloat key field increment
返回值是增加后的值
若是没有对应的 key-field 那么就默认以0开始
也可以加一个负数
对一个值增加
127.0.0.1:6379> hincrbyfloat key1 f1 0.5
211.5
对一个没有的增加
127.0.0.1:6379> hincrbyfloat key1 f6 0.5
0.5
ziphash:压缩链表
hashtable: 普通的hash表
如果 hash 表中国的元素个数比较少,那么使用 ziplist,如果元素个数比较多,那么就是用hashtable
每个 value 的长度比较短,使用zipist,如果value的长度比较长的话,也会使用 hashtable