Redis五大数据类型
前言
Redis的五种数据类型:String、List、Set、Zset、Hash。
参考文档:http://redisdoc.com/
一、字符串String
String 是 redis 最基本的类型,一个 key 对应一个 value。string 类型是二进制安全的。
1. set / get / del / append / strlen
命令:
· set (key) (value) : 设置键值对,保存数据
· get (key) : 查询key对应的value
· del (key) :删除key对应的数据
· append (key) (value) :向指定的key的value后追加数据
· strlen (key) :返回key的value的长度(字符数量)
代码如下(示例):
127.0.0.1:6379> set k1 v1 # 设置数据(k1,v1)
OK
127.0.0.1:6379> set k2 v2 # 设置数据(k2,v2)
OK
127.0.0.1:6379> keys * # 查询所有的key
1) "k1"
2) "k2"
127.0.0.1:6379> del k2 # 删除数据k2
(integer) 1
127.0.0.1:6379> keys * # 查询所有的key
1) "k1"
127.0.0.1:6379> get k1 # 获取数据k1
"v1"
127.0.0.1:6379> append k1 abc # 往k1的值追加数据abc
(integer) 5 # 返回值的长度(字符数量)
127.0.0.1:6379> get k1
"v1abc"
127.0.0.1:6379> strlen k1 # 返回k1值的长度(字符数量)
(integer) 5
2. incr / decr / incrby / decrby
加减操作,操作的必须是数字类型
incr:意思是increment,增加
decr:意思是decrement,减少
命令:
· incr (key) : key对应的value加1,相当于++
· decr (key) :key对应的value减1,相当于–
· incrby (key) (number) :key对应的value自增number,相当于+=
· decrby (key) (number) :key对应的value自减number,相当于-=
代码如下(示例):
127.0.0.1:6379> set k1 1 # 初始化k1的值为1
OK
127.0.0.1:6379> incr k1 # k1自增1(相当于++)
(integer) 2
127.0.0.1:6379> incr k1
(integer) 3
127.0.0.1:6379> get k1
"3"
127.0.0.1:6379> decr k1 # k1自减1(相当于--)
(integer) 2
127.0.0.1:6379> decr k1
(integer) 1
127.0.0.1:6379> get k1
"1"
127.0.0.1:6379> incrby k1 3 # k1自增3(相当于+=3)
(integer) 4
127.0.0.1:6379> get k1
"4"
127.0.0.1:6379> decrby k1 2 # k1自减2(相当于-=2)
(integer) 2
127.0.0.1:6379> get k1
"2"
3. getrange / setrange
类似between…and…
range:范围
命令:
· getrange (key) (begin) (end) : 查询[begin,end]下标范围内的值,如果是(0,-1)就是查询全部的值
· setrange (key) (begin) (xxxx) :从begin下标开始设置xxx值,将原有的替换掉
代码如下(示例):
127.0.0.1:6379> set k1 abcdef # 初始化k1的值为abcdef
OK
127.0.0.1:6379> get k1
"abcdef"
127.0.0.1:6379> getrange k1 0 -1 # 查询k1全部的值
"abcdef"
127.0.0.1:6379> getrange k1 0 3 # 查询k1的值,范围是下标0~下标3(包含0和3,共 返回4个字符)
"abcd"
127.0.0.1:6379> setrange k1 1 xxx # 替换k1的值,从下标1开始提供为xxx
(integer) 6
127.0.0.1:6379> get k1
"axxxef"
4. setex / setnx
命令:
· setex (key) (seconds) (value) : 添加k1 v1数据的同时,设置seconds秒的生命周期· setnx (key) (value) :添加数据的时候判断是否已经存在,防止已存在的数据被覆盖掉
代码如下(示例):
127.0.0.1:6379> setex k1 5 v1 # 添加k1 v1数据的同时,设置5秒的生命周期
OK
127.0.0.1:6379> get k1 # 未过期,k1的值可以获取到
"v1"
127.0.0.1:6379> get k1 # 已过期,k1的值v1自动销毁
(nil)
127.0.0.1:6379> setex k1 v1 # k1不存在,所以添加成功
OK
127.0.0.1:6379> setnx k1 abc
(integer) 0 # 添加失败,因为k1已经存在
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> setnx k2 xyz
(integer) 1 # k2不存在,所以添加成功
5. mset / mget / msetnx
命令:
· mset (key1) (value1) (key2) (value2) :用于同时设置一个或多个 key-value 对· mget (key1) (key2) :返回所有(一个或多个)给定 key 的值(如果某个key不存在,不存在的key返回null)
· msetnx (key1) (value1) (key2) (value2) :一次添加多条数据,当所有 key 都成功设置,返回 1 。 如果有一个key设置失败,所有的key设置都会失败,返回 0 。原子操作
代码如下(示例):
127.0.0.1:6379> set k1 v1 k2 v2 # set不支持一次添加多条数据
(error) ERR syntax error
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # mset可以一次添加多条数据
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
3) "k3"
127.0.0.1:6379> mget k2 k3 # 一次获取多条数据
1) "v2"
2) "v3"
127.0.0.1:6379> msetnx k3 v3 k4 v4 # 一次添加多条数据时,如果添加的数据中有已经存在的,则失败
(integer) 0
127.0.0.1:6379> msetnx k4 v4 k5 v5 # 一次添加多条数据时,如果添加的数据中都不存在的,则成功
(integer) 1
6. getset
命令:
· getset (key) (value) :先get再set,返回旧值,如果没有旧值返回nil
代码如下(示例):
127.0.0.1:6379> getset k6 v6
(nil) # 因为没有k6,所以get为null,然后将k6v6的值添加到数据库
127.0.0.1:6379> keys *
1) "k4"
2) "k1"
3) "k2"
4) "k3"
5) "k5"
6) "k6"
127.0.0.1:6379> get k6
"v6"
127.0.0.1:6379> getset k6 vv6 # 先获取k6的值,然后修改k6的值为vv6
"v6" # 返回旧值
127.0.0.1:6379> get k6
"vv6" # 返回新值
二、列表List
1. lpush / rpush / lrange
- l:left 自左向右→添加 (从上往下添加)
- r:right 自右向左←添加(从下往上添加)
代码如下(示例):
127.0.0.1:6379> lpush list01 1 2 3 4 5 # 从上往下添加
(integer) 5
127.0.0.1:6379> keys *
1) "list01"
127.0.0.1:6379> lrange list01 0 -1 # 查询list01中的全部数据0表示开始,-1表示结尾
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> rpush list02 1 2 3 4 5 # 从下往上添加
(integer) 5
127.0.0.1:6379> lrange list02 0 -1 #返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
2. lpop/rpop
- lpop (list):移除左边第一个元素
- rpop (list):移除右边第一个元素
代码如下(示例):
127.0.0.1:6379> lrange list02 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> lpop list02 # 从左(上)边移除第一个元素
"1"
127.0.0.1:6379> rpop list02 # 从右(下)边移除第一个元素
"5"
3. lindex
- lindex (list) (index): 根据下标查询元素(从左向右,自上而下)
代码如下(示例):
127.0.0.1:6379> lrange list01 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> lindex list01
2 # 从上到下数,下标为2的值 "3"
127.0.0.1:6379> lindex list01
1 # 从上到下数,下标为1的值 "4"
4. llen:返回集合长度
代码如下(示例):
127.0.0.1:6379> llen list01
(integer) 5
5. lrem:删除n个value
代码如下(示例):
127.0.0.1:6379> lpush list01 1 2 2 3 3 3 4 4 4 4
(integer) 10
127.0.0.1:6379> lrem list01 2 3 # 从list01中移除2个3
(integer) 2
127.0.0.1:6379> lrange list01 0 -1
1) "4"
2) "4"
3) "4"
4) "4"
5) "3"
6) "2"
7) "2"
8) "1"
6. ltrim:截取指定范围的值,别的全扔掉
- ltrim key begindex endindex
代码如下(示例):
127.0.0.1:6379> lpush list01 1 2 3 4 5 6 7 8 9
(integer) 9
127.0.0.1:6379> lrange list01 0 -1
1) "9" # 下标0
2) "8" # 下标1
3) "7" # 下标2
4) "6" # 下标3
5) "5" # 下标4
6) "4" # 下标5
7) "3" # 下标6
8) "2" # 下标7
9) "1" # 下标8
127.0.0.1:6379> ltrim list01 3 6 # 截取下标3~6的值,别的全扔掉
OK
127.0.0.1:6379> lrange list01 0 -1
1) "6"
2) "5"
3) "4"
4) "3"
7. rpoplpush:从一个集合搞一个元素到另一个集合中(右出一个,左进一个)
代码如下(示例):
127.0.0.1:6379> rpush list01 1 2 3 4 5
(integer) 5
127.0.0.1:6379> lrange list01 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> rpush list02 1 2 3 4 5
(integer) 5
127.0.0.1:6379> lrange list02 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> rpoplpush list01 list02 # list01右边出一个,从左进入到 list02的第一个位置
"5"
127.0.0.1:6379> lrange list01 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> lrange list02 0 -1
1) "5"
2) "1"
3) "2"
4) "3"
5) "4"
6) "5
8. lset:改变某个下标的某个值
- lset key index value
代码如下(示例):
127.0.0.1:6379> lrange list02 0 -1
1) "5"
2) "1"
3) "2"
4) "3"
5) "4"
6) "5"
127.0.0.1:6379> lset list02 0 x # 将list02中下标为0的元素修改成x
OK
127.0.0.1:6379> lrange list02 0 -1
1) "x"
2) "1"
3) "2"
4) "3"
5) "4"
6) "5"
9. linsert:插入元素(指定某个元素之前/之后)
- linsert key before/after oldvalue newvalue
代码如下(示例):
127.0.0.1:6379> lrange list02 0 -1
1) "x"
2) "1"
3) "2"
4) "3"
5) "4"
6) "5"
127.0.0.1:6379> linsert list02 before 2 java # 从左边进入,在list02中的 2元素之前插入java
(integer) 7
127.0.0.1:6379> lrange list02 0 -1
1) "x"
2) "1"
3) "java"
4) "2"
5) "3"
6) "4"
7) "5"
127.0.0.1:6379> linsert list02 after 2 redis # 从左边进入,在list02中的 2元素之后插入redis
(integer) 8
127.0.0.1:6379> lrange list02 0 -1
1) "x"
2) "1"
3) "java"
4) "2"
5) "redis"
6) "3"
7) "4"
8) "5"
- 性能总结:类似添加火车皮一样,头尾操作效率高,中间操作效率惨;
三、集合Set
- 和java中的set特点类似,不允许重复
1. sadd/smembers/sismember:添加/查看/判断是否存在
代码如下(示例):
127.0.0.1:6379> sadd set01 1 2 2 3 3 3 # 添加元素(自动排除重复元素)
(integer) 3
127.0.0.1:6379> smembers set01 # 查询set01集合
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> sismember set01 2
(integer) 1 # 存在
127.0.0.1:6379> sismember set01 5
(integer) 0 # 不存在
# 注意:1和0可不是下标,而是布尔。1:true存在,2:false不存在
2. scard:获得集合中的元素个数
代码如下(示例):
127.0.0.1:6379> scard set01
(integer) 3 # 集合中有3个元素
3. srem:删除集合中的元素
- srem key value
代码如下(示例):
127.0.0.1:6379> srem set01 2 # 移除set01中的元素2
(integer) 1 # 1表示移除成功
4. srandmember:从集合中随机获取几个元素
- srandmember 整数(个数)
代码如下(示例):
127.0.0.1:6379> sadd set01 1 2 3 4 5 6 7 8 9
(integer) 9
127.0.0.1:6379> smembers set01
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
9) "9"
127.0.0.1:6379> srandmember set01 3 # 从set01中随机获取3个元素
1) "8"
2) "2"
3) "3"
127.0.0.1:6379> srandmember set01 5 # 从set01中随机获取5个元素
1) "5"
2) "8"
3) "7"
4) "4"
5) "6"
5. spop:随机出栈(移除)
代码如下(示例):
127.0.0.1:6379> smembers set01
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
9) "9"
127.0.0.1:6379> spop set01 # 随机移除一个元素
"8"
127.0.0.1:6379> spop set01 # 随机移除一个元素
"7"
6. smove:移动元素:将key1某个值赋值给key2
代码如下(示例):
127.0.0.1:6379> sadd set01 1 2 3 4 5
(integer) 5
127.0.0.1:6379> sadd set02 x y z
(integer) 3
127.0.0.1:6379> smove set01 set02 3 # 将set01中的元素3移动到set02中
(integer) 1 # 移动成功
7. 数学集合类
- 交集:sinter
- 并集:sunion
- 差集:sdiff
代码如下(示例):
127.0.0.1:6379> sadd set01 1 2 3 4 5
(integer) 5
127.0.0.1:6379> sadd set02 2 a 1 b 3
(integer) 5
127.0.0.1:6379> sinter set01 set02 # set01和set02共同存在的元素
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> sunion set01 set02 # 将set01和set02中所有元素合并起来(排除 重复的)
1) "5"
2) "4"
3) "3"
4) "2"
5) "b"
6) "a"
7) "1"
127.0.0.1:6379> sdiff setr01 set02
(empty list or set)
127.0.0.1:6379> sdiff set01 set02 # 在set01中存在,在set02中不存在
1) "4"
2) "5"
127.0.0.1:6379> sdiff set02 set01 # 在set02中存在,在set01中不存在
1) "b"
2) "a"
四、哈希Hash
- 类似java里面的Map<String,Object>
KV模式不变,但V是一个键值对
1. hset/hget/hmset/hmget/hgetall/hdel:添加/得到/多添加/多得到/得到全部/删除属性
代码如下(示例):
127.0.0.1:6379> hset user id 1001 # 添加user,值为id=1001
(integer) 1
127.0.0.1:6379> hget user
(error) ERR wrong number of arguments for 'hget' command
127.0.0.1:6379> hget user id # 查询user,必须指明具体的字段
"1001"
127.0.0.1:6379> hmset student id 101 name tom age 22 # 添加学生student,属 性一堆 OK
127.0.0.1:6379> hget student name # 获取学生名字
"tom"
127.0.0.1:6379> hmget student name age # 获取学生年龄
1) "tom"
2) "22"
127.0.0.1:6379> hgetall student # 获取学生全部信息
1) "id"
2) "101"
3) "name"
4) "tom"
5) "age"
6) "22"
127.0.0.1:6379> hdel student age # 删除学生年龄属性
(integer) 1 # 删除成功
127.0.0.1:6379> hgetall student
1) "id"
2) "101"
3) "name"
4) "tom"
2. hlen:返回元素的属性个数
代码如下(示例):
127.0.0.1:6379> hgetall student
1) "id"
2) "101"
3) "name"
4) "tom"
127.0.0.1:6379> hlen student
(integer) 2 # student属性的数量,id和name,共两个属性
3. hexists:判断元素是否存在某个属性
代码如下(示例):
127.0.0.1:6379> hexists student name # student中是否存在name属性
(integer) 1 # 存在
127.0.0.1:6379> hexists student age # student中是否存在age属性
(integer) 0 # 不存在
4. hkeys/hvals:获得属性的所有key/获得属性的所有value
代码如下(示例):
127.0.0.1:6379> hkeys student # 获取student所有的属性名
1) "id"
2) "name"
127.0.0.1:6379> hvals student # 获取student所有属性的值(内容)
1) "101"
2) "tom"
5. hincrby/hincrbyfloat:自增(整数)/自增(小数)
代码如下(示例):
127.0.0.1:6379> hmset student id 101 name tom age 22
OK
127.0.0.1:6379> hincrby student age 2 # 自增整数2
(integer) 24
127.0.0.1:6379> hget student age "24"
127.0.0.1:6379> hmset user id 1001 money 1000
OK
127.0.0.1:6379> hincrbyfloat user money 5.5 # 自增小数5.5
"1005.5"
127.0.0.1:6379> hget user money
"1005.5"
6. hsetnx:添加的时候,先判断是否存在
代码如下(示例):
127.0.0.1:6379> hsetnx student age 18 # 添加时,判断age是否存在 (
integer) 0 # 添加失败,因为age已存在
127.0.0.1:6379> hsetnx student sex 男 # 添加时,判断sex是否存在
(integer) 1 # 添加成功,因为sex不存在
127.0.0.1:6379> hgetall student
1) "id"
2) "101"
3) "name"
4) "tom"
5) "age"
6) "24"
7) "sex"
8) "\xe7\x94\xb7" # 可以添加中文,但是显示为乱码(后期解决)
五、有序集合Zset
- 真实需求:充10元可享vip1; 充20元可享vip2; 充30元可享vip3;以此类推…
1. zadd/zrange (withscores):添加/查询
代码如下(示例):
127.0.0.1:6379> zadd zset01 10 vip1 20 vip2 30 vip3 40 vip4 50 vip5
(integer) 5
127.0.0.1:6379> zrange zset01 0 -1 # 查询数据
1) "vip1"
2) "vip2"
3) "vip3"
4) "vip4"
5) "vip5"
127.0.0.1:6379> zrange zset01 0 -1 withscores # 带着分数查询数据
1) "vip1"
2) "10"
3) "vip2"
4) "20"
5) "vip3"
6) "30"
7) "vip4"
8) "40"
9) "vip5"
10) "50"
2. zrangebyscore:模糊查询
- ( : 不包含
- limit:跳过几个截取几个
代码如下(示例):
127.0.0.1:6379> zrangebyscore zset01 20 40 # 20 <= score <= 40
1) "vip2"
2) "vip3"
3) "vip4"
127.0.0.1:6379> zrangebyscore zset01 20 (40 # 20 <= score < 40
1) "vip2"
2) "vip3"
127.0.0.1:6379> zrangebyscore zset01 (20 (40 # 20 < score < 40
1) "vip3"
127.0.0.1:6379> zrangebyscore zset01 10 40 limit 2 2 # 10 <= score <= 40,共返回四个,跳过前2个,取2个
1) "vip3"
2) "vip4"
127.0.0.1:6379> zrangebyscore zset01 10 40 limit 2 1 # 20 <= score <= 40,共返回四个,跳过前2个,取1个
1) "vip3"
3. zrem:删除元素
代码如下(示例):
127.0.0.1:6379> zrem zset01 vip5 # 移除vip5
(integer) 1
4. zcard/zcount/zrank/zscore:集合长度/范围内元素个数/得元素下标/通过值得分数
代码如下(示例):
127.0.0.1:6379> zcard zset01 # 集合中元素的个数
(integer) 4
127.0.0.1:6379> zcount zset01 20 30 # 分数在20~40之间,共有几个元素
(integer) 2
127.0.0.1:6379> zrank zset01 vip3 # vip3在集合中的下标(从上向下) 0 1 2 3 4
(integer) 2
127.0.0.1:6379> zscore zset01 vip2 # 通过元素获得对应的分数
"20"
5. zrevrank:逆序找下标(从下向上)
代码如下(示例):
127.0.0.1:6379> zrevrank zset01 vip3
(integer) 1
6. zrevrange:逆序查询
代码如下(示例):
127.0.0.1:6379> zrange zset01 0 -1 # 顺序查询
1) "vip1"
2) "vip2"
3) "vip3"
4) "vip4"
127.0.0.1:6379> zrevrange zset01 0 -1 # 逆序查询
1) "vip4"
2) "vip3"
3) "vip2"
4) "vip1"
7. zrevrangebyscore:逆序范围查找
代码如下(示例):
127.0.0.1:6379> zrevrangebyscore zset01 30 20 # 逆序查询分数在30~20之间的 (注意,先写大值,再写小值)
1) "vip3"
2) "vip2"
127.0.0.1:6379> zrevrangebyscore zset01 20 30 # 如果小值在前,则结果为null
(empty list or set)
总结
Redis 是一种运行速度很快,并发性能很强,并且运行在内存上的NoSql(not only sql)数据库。NoSQL数据库无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。
分布式数据库的CAP:
C(Consistency):强一致性
A(Availability):高可用性
P(Partition tolerance):分区容错性