127.0.0.1:6379> flushdb
OK
# 查看所有key127.0.0.1:6379> keys *
(empty list or set)127.0.0.1:6379>set name qs
OK
127.0.0.1:6379>set age 18
OK
127.0.0.1:6379> keys *
1)"age"2)"name"# 是否存在key=name127.0.0.1:6379> exists name
(integer)1# 移除key=name,数量1127.0.0.1:6379> move name 1(integer)1127.0.0.1:6379> keys *
1)"age"
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379>set name qs
OK
# 设置key过期时间,单位秒127.0.0.1:6379> expire name 10(integer)1# 查看key的剩余时间127.0.0.1:6379> ttl name
(integer)5127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> get name
(nil)127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379>set name qs
OK
127.0.0.1:6379>set age 18
OK
# 查看key的类型127.0.0.1:6379>type name
string
127.0.0.1:6379>type age
string
二、五大数据类型
1. String 字符串
1.1 append & strlen
append:追加字符串,当前 key 不存在,就 set key。
strlen:获取字符串的长度。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379>set key1 hello
OK
127.0.0.1:6379> get key1
"hello"# 追加字符串,当前`key`不存在,就`set key`127.0.0.1:6379> append key1 ' world'(integer)11127.0.0.1:6379> get key1
"hello world"# 获取字符串的长度127.0.0.1:6379> strlen key1
(integer)11
1.2 incr & decr & incrby & decrby
incr:++1。
decr:–1。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379>set num 0
OK
127.0.0.1:6379> get num
"0"127.0.0.1:6379> incr num
(integer)1127.0.0.1:6379> incr num
(integer)2127.0.0.1:6379> get num
"2"127.0.0.1:6379> decr num
(integer)1127.0.0.1:6379> decr num
(integer)0127.0.0.1:6379> decr num
(integer) -1
127.0.0.1:6379> get num
"-1"
incrby:+=步长。
decrby:-=步长。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379>set num 0
OK
127.0.0.1:6379> get num
"0"127.0.0.1:6379> incrby num 10(integer)10127.0.0.1:6379> incrby num 10(integer)20127.0.0.1:6379> get num
"20"127.0.0.1:6379> decrby num 5(integer)15127.0.0.1:6379> decrby num 15(integer)0127.0.0.1:6379> get num
"0"
1.3 getrange & setrange
getrange:截取字符串。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379>set key1 'hello world'
OK
127.0.0.1:6379> get key1
"hello world"# 截取字符串[0...3]127.0.0.1:6379> getrange key1 03"hell"127.0.0.1:6379> getrange key1 26"llo w"# 截取全部字符串,相当于get key127.0.0.1:6379> getrange key1 0 -1
"hello world"
setrange:替换字符串。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379>set key1 'hello world'
OK
127.0.0.1:6379> get key1
"hello world"# 替换指定位置开始的字符串127.0.0.1:6379> setrange key1 6 redis
(integer)11127.0.0.1:6379> get key1
"hello redis"
1.4 setex & setnx
setex:设置过期时间。
127.0.0.1:6379> flushdb
OK
# 设置`key=hello`30秒过期127.0.0.1:6379> setex key1 30 hello
OK
127.0.0.1:6379> get key1
"hello"127.0.0.1:6379> ttl key1
(integer)21127.0.0.1:6379> ttl key1
(integer)6127.0.0.1:6379> ttl key1
(integer) -2
setnx:不存在设置,存在失败(常用在分布式锁)。
127.0.0.1:6379> flushdb
OK
# 不存在设置成功127.0.0.1:6379> setnx name qs
(integer)1# 存在设置失败127.0.0.1:6379> setnx name wy
(integer)0127.0.0.1:6379> get name
"qs"127.0.0.1:6379> setnx age 18(integer)1
127.0.0.1:6379> flushdb
OK
# set设置对象Json字符串127.0.0.1:6379>set user:1 {name:qs,age:18}
OK
127.0.0.1:6379> get user:1
"{name:qs,age:18}"# 设置对象属性127.0.0.1:6379> mset user:2:name wy user:2:age 20
OK
127.0.0.1:6379> keys *
1)"user:2:age"2)"user:1"3)"user:2:name"# 获取对象多个属性127.0.0.1:6379> mget user:2:name user:2:age
1)"wy"2)"20"
1.6 getset
127.0.0.1:6379> flushdb
OK
# 获取原值,设置新值127.0.0.1:6379> getset name qs
(nil)127.0.0.1:6379> get name
"qs"127.0.0.1:6379> getset name wy
"qs"127.0.0.1:6379> get name
"wy"
2. List 列表
在 Redis 里面,可以把 List 用做 栈、队列、阻塞队列。
2.1 lpush & rpush & lpop & rpop & lrange
lpush:在集合左侧添加元素。
rpush:在集合右侧添加元素。
lpop:在集合左侧移除元素。
rpop:在集合右侧移除元素。
lrange:通过截取查看集合元素。
127.0.0.1:6379> flushdb
OK
# 左侧添加元素127.0.0.1:6379> lpush list one
(integer)1127.0.0.1:6379> lpush list two
(integer)2127.0.0.1:6379> lrange list 0 -1
1)"two"2)"one"(1.76s)# 右侧添加元素127.0.0.1:6379> rpush list 1(integer)3127.0.0.1:6379> lrange list 0 -1
1)"two"2)"one"3)"1"# 左侧移除元素127.0.0.1:6379> lpop list
"two"# 右侧移除元素127.0.0.1:6379> rpop list
"1"127.0.0.1:6379> lrange list 0 -1
1)"one"
2.2 lindex & llen
lindex:通过下标获取集合元素。
llen:获取集合长度。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush list one two three four five six seven eight nine ten
(integer)10127.0.0.1:6379> lrange list 0 -1
1)"ten"2)"nine"3)"eight"4)"seven"5)"six"6)"five"7)"four"8)"three"9)"two"10)"one"127.0.0.1:6379> lindex list 1"nine"127.0.0.1:6379> lindex list 0"ten"# 获取集合长度127.0.0.1:6379> llen list
(integer)10
2.3 lrem
lrem:移除集合元素,指定个数。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush list one two three three three
(integer)5127.0.0.1:6379> lrange list 0 -1
1)"three"2)"three"3)"three"4)"two"5)"one"# 移除集合元素,指定个数 127.0.0.1:6379> lrem list 1 one
(integer)1127.0.0.1:6379> lrem list 2 three
(integer)2127.0.0.1:6379> lrange list 0 -1
1)"three"2)"two"
2.4 ltrim
ltrim:截取集合元素。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush list one two three four five six
(integer)6127.0.0.1:6379> lrange list 0 -1
1)"six"2)"five"3)"four"4)"three"5)"two"6)"one"# 截取集合元素127.0.0.1:6379> ltrim list 13
OK
127.0.0.1:6379> lrange list 0 -1
1)"five"2)"four"3)"three"
2.5 rpoplpush
rpoplpush:移除集合最左一个元素,添加到新的集合。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush list one two three
(integer)3# 移除集合最左一个元素添加到新的集合127.0.0.1:6379> rpoplpush list newlist
"one"127.0.0.1:6379> keys *
1)"newlist"2)"list"127.0.0.1:6379> lrange list 0 -1
1)"three"2)"two"127.0.0.1:6379> lrange newlist 0 -1
1)"one"
2.6 lset
lset:设置集合指定下标的值。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush list one two three four
(integer)4# 设置下标0的值为1127.0.0.1:6379> lset list 01
OK
127.0.0.1:6379> lrange list 0 -1
1)"1"2)"three"3)"two"4)"one"# 下标不存在报错127.0.0.1:6379> lset list 44(error) ERR index out of range
2.7 linsert
linsert:在集合指定元素左右,插入新元素。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush list one two three four
(integer)4# 在集合指定元素左边插入新元素127.0.0.1:6379> linsert list before one 1(integer)5127.0.0.1:6379> lrange list 0 -1
1)"four"2)"three"3)"two"4)"1"5)"one"# 在集合指定元素右边插入新元素127.0.0.1:6379> linsert list after one -1
(integer)6127.0.0.1:6379> lrange list 0 -1
1)"four"2)"three"3)"two"4)"1"5)"one"6)"-1"
3. Set 无序集合
Set 无序不重复集合。
3.1 sadd & smembers & sismember & scard
sadd:Set 集合添加元素。
smembers: 查看指定集合所有值。
sismember:判断集合是否存在某个值。
scard:获取集合元素个数。
127.0.0.1:6379> flushdb
OK
# Set集合添加元素127.0.0.1:6379> sadd set one two three three three
(integer)3# 查看指定集合所有值127.0.0.1:6379> smembers set1)"one"2)"three"3)"two"# 判断集合是否存在某个值127.0.0.1:6379> sismember set three
(integer)1127.0.0.1:6379> sismember set four
(integer)0# 获取集合元素个数127.0.0.1:6379> scard set(integer)3
3.2 srem
srem:移除集合指定元素。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> sadd set one two three four
(integer)4# 移除集合指定元素127.0.0.1:6379> srem set three
(integer)1127.0.0.1:6379> scard set(integer)3127.0.0.1:6379> smembers set1)"four"2)"one"3)"two"
3.3 srandmember
srandmember:随机抽取元素。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> sadd set one two three four
(integer)4127.0.0.1:6379> smembers set1)"four"2)"one"3)"three"4)"two"# 随机抽取一个元素127.0.0.1:6379> srandmember set"two"# 随机抽取两个元素127.0.0.1:6379> srandmember set21)"one"2)"four"127.0.0.1:6379> smembers set1)"four"2)"one"3)"three"4)"two"
3.4 spop
spop:随机移除元素。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> sadd set one two three four
(integer)4127.0.0.1:6379> smembers set1)"four"2)"one"3)"three"4)"two"# 随机移除一个元素127.0.0.1:6379> spop set"four"(0.94s)# 随机移除两个元素127.0.0.1:6379> spop set21)"one"2)"three"127.0.0.1:6379> smembers set1)"two"
3.5 smove
smove:移除指定元素到新集合。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> sadd set one two three four
(integer)4# 移除`one`元素到`newset`集合。127.0.0.1:6379> smove set newset one
(integer)1127.0.0.1:6379> keys *
1)"newset"2)"set"127.0.0.1:6379> smembers set1)"four"2)"three"3)"two"127.0.0.1:6379> smembers newset
1)"one"
3.6 sdiff & sinter & sunion
sdiff:差集。
sinter:交集。
sunion:并集。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> sadd set1 one two three four
(integer)4127.0.0.1:6379> sadd set2 three four five six
(integer)4# 差集127.0.0.1:6379>sdiff set1 set2
1)"one"2)"two"# 交集127.0.0.1:6379> sinter set1 set2
1)"four"2)"three"# 并集127.0.0.1:6379> sunion set1 set2
1)"one"2)"three"3)"two"4)"five"5)"six"6)"four"
4. Hash 哈希
Map 集合。
Hash 更适合于对象的存储。
String 更加适合字符串存储。
4.1 hset & hget & hmset & hmget & hgetall
hset:设置一个 key-value。
hget:获取一个 key。
hmset:设置多个 key-value。
hmget:获取多个 key。
hgetall:获取所有 key-value。
127.0.0.1:6379> flushdb
OK
# 设置一个key-value127.0.0.1:6379> hset hash name qs
(integer)1(1.72s)127.0.0.1:6379> hget hash name
"qs"127.0.0.1:6379> hmset hash age 18 sex 1
OK
127.0.0.1:6379> hmget hash name age sex
1)"qs"2)"18"3)"1"# 获取所有`key-value`127.0.0.1:6379> hgetall hash1)"name"2)"qs"3)"age"4)"18"5)"sex"6)"1"
4.2 hdel
hdel:删除 hash 指定 key。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> hset hash name qs
(integer)1127.0.0.1:6379> hset hash age 18(integer)1127.0.0.1:6379> keys *
1)"hash"127.0.0.1:6379> hgetall hash1)"name"2)"qs"3)"age"4)"18"# 删除`hash`指定`key`127.0.0.1:6379> hdel hash name
(integer)1127.0.0.1:6379> hgetall hash1)"age"2)"18"
4.3 hlen
hlen:获取 hash 的 key 数量。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> hmset hash name qs age 18 sex 1
OK
127.0.0.1:6379> hgetall hash1)"name"2)"qs"3)"age"4)"18"5)"sex"6)"1"# 获取`hash`的`key`数量127.0.0.1:6379> hlen hash(integer)3
4.4 hexists
hexists:hash 中是否存在 key=name。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> hmset hash name qs age 18 sex 1
OK
# hash中是否存在key=name127.0.0.1:6379> hexists hash name
(integer)1127.0.0.1:6379> hexists hash salary
(integer)0
4.5 hkeys & hvals
hkeys:获取所有 key。
hvals:获取所有 value。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> hmset hash name qs age 18 sex 1
OK
# 获取所有key127.0.0.1:6379> hkeys hash1)"name"2)"age"3)"sex"# 获取所有value127.0.0.1:6379> hvals hash1)"qs"2)"18"3)"1"127.0.0.1:6379> hgetall hash1)"name"2)"qs"3)"age"4)"18"5)"sex"6)"1"
4.6 hincrby
hincrby:hash 集合指定字段值 += 步长。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> hmset hash num1 0
OK
# hash集合指定字段值+=步长127.0.0.1:6379> hincrby hash num1 2(integer)2127.0.0.1:6379> hincrby hash num1 -1
(integer)1
4.7 hsetnx
hsetnx:key 不存在可以设置。
127.0.0.1:6379> flushdb
OK
# key不存在可以设置127.0.0.1:6379> hsetnx hash name qs
(integer)1# key存在不能设置127.0.0.1:6379> hsetnx hash name wy
(integer)0
5. Zset 有序集合
有序集合。
5.1 zadd & zrange
zadd:添加元素。
127.0.0.1:6379> flushdb
OK
# 添加一个指定顺序号的元素127.0.0.1:6379> zadd zset 1 one
(integer)1(1.53s)# 添加两个指定顺序号的元素127.0.0.1:6379> zadd zset 2 two 3 three
(integer)2127.0.0.1:6379> zrange zset 0 -1
1)"one"2)"two"3)"three"
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> zadd zset 1 one 2 two 3 three 4 four
(integer)4127.0.0.1:6379> zrange zset 0 -1
1)"one"2)"two"3)"three"4)"four"# 移除集合指定元素127.0.0.1:6379> zrem zset three four
(integer)2# 获取集合元素个数127.0.0.1:6379> zcard zset
(integer)2# 获取指定区间元素个数127.0.0.1:6379> zcount zset 12(integer)2
127.0.0.1:6379> flushdb
OK
# 创建第一组元素127.0.0.1:6379> pfadd uv1 a b c d
(integer)1127.0.0.1:6379> pfcount uv1
(integer)4# 创建第二组元素127.0.0.1:6379> pfadd uv2 d e f f
(integer)1127.0.0.1:6379> pfcount uv2
(integer)3# 重复元素添加失败127.0.0.1:6379> pfadd uv2 f
(integer)0127.0.0.1:6379> pfcount uv2
(integer)3# 合并两组元素,uv3 = uv1 + uv2 并集127.0.0.1:6379> pfmerge uv3 uv1 uv2
OK
127.0.0.1:6379> pfcount uv3
(integer)6127.0.0.1:6379> keys *
1)"uv2"2)"uv3"3)"uv1"
127.0.0.1:6379> flushdb
OK
# 开启事务127.0.0.1:6379> multi
OK
# 命令入队127.0.0.1:6379>set k1 v1
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379>set k1 vv
QUEUED
127.0.0.1:6379>set k2 v2
QUEUED
# 执行事务127.0.0.1:6379>exec1) OK
3)"v1"2) OK
4) OK
2. 事务放弃执行
127.0.0.1:6379> flushdb
OK
# 开始事务127.0.0.1:6379> multi
OK
127.0.0.1:6379>set k1 v1
QUEUED
127.0.0.1:6379>set k2 v2
QUEUED
127.0.0.1:6379>set k3 v3
QUEUED
# 取消事务127.0.0.1:6379> discard
OK
127.0.0.1:6379> mget k1 k2 k3
1)(nil)2)(nil)3)(nil)
3. 编译型异常
比如命令错误,事务中所有命令都不会被执行。
127.0.0.1:6379> flushdb
OK
# 开启事务127.0.0.1:6379> multi
OK
127.0.0.1:6379>set k1 v1
QUEUED
127.0.0.1:6379> getset k1 v1
QUEUED
# 错误命令,报错127.0.0.1:6379> getset k3
(error) ERR wrong number of arguments for'getset'command# 执行事务,报错127.0.0.1:6379>exec(error) EXECABORT Transaction discarded because of previous errors.
# 所有命令都不会成功127.0.0.1:6379> keys *
(empty list or set)
4. 运行时异常
如果 事务队列 中存在语法性,那么执行命令的时候。 其他命令是可以正常执行的,错误命令抛出异常。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379>set k1 v1
OK
# 开启事务127.0.0.1:6379> multi
OK
127.0.0.1:6379> get k1
QUEUED
# 字符串自增,报错127.0.0.1:6379> incr k1
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379>set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
# 执行事务127.0.0.1:6379>exec1)"v1"2)(error) ERR value is not an integer or out of range
# 第二条命令报错,后面执行正常3)"v1"4) OK
5)"v2"127.0.0.1:6379> keys *
1)"k1"2)"k2"
5. watch 监视
悲观锁。
很悲观,认为什么时候都会出问题,无论做什么都会加锁。
乐观锁。
很乐观,认为什么时候都不会出问题,所以不会上锁。
更新数据的时候去判断一下,在此期间是否有人修改过这个数据。
先获取 Version,更新的时候比较 Version。
线程一。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379>set money 100
OK
127.0.0.1:6379>set pay 0
OK
# 监听`money`,获取`Version`127.0.0.1:6379>watch money
OK
# 开启事务127.0.0.1:6379> multi
OK
# 加20127.0.0.1:6379> incrby pay 20
QUEUED
# 减20127.0.0.1:6379> decrby money 20
QUEUED
# 等待执行事务