相关命令:https://www.runoob.com/redis/redis-benchmarks.html(具体以官网为准)
测试:50个客户端,共10W个请求
redis-benchmark -h localhost -p 6379 -c 50 -n 100000
结果分析图:
默认有16个数据库密(0-15),且默认使用0库
清除当前数据库用flushdb,清除所有数据库用flushalll
五大基本数据类型
Redis-key
127.0.0.1:6379> set name lijie1
OK
127.0.0.1:6379> set id 666
OK
127.0.0.1:6379> keys * #查看所有key
1) "id"
2) "name"
127.0.0.1:6379> exists name #判断key是否存在
(integer) 1
127.0.0.1:6379> expire name 20 #设置过期时间,单位S
(integer) 1
127.0.0.1:6379> ttl name #查看当前key的剩余时间
(integer) 12
127.0.0.1:6379> ttl name
(integer) 11
127.0.0.1:6379> ttl name
(integer) 8
127.0.0.1:6379> ttl name
(integer) 5
127.0.0.1:6379> ttl name
(integer) 3
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> keys *
1) "id"
127.0.0.1:6379> type id #查看当前key的类型
string
127.0.0.1:6379>
- String
127.0.0.1:6379> set name lijie OK 127.0.0.1:6379> append name ,666 #追加,若key无,则新建 (integer) 9 127.0.0.1:6379> get name "lijie,666" 127.0.0.1:6379> strlen name #字符串长度 (integer) 9 127.0.0.1:6379>
实现自增自减
127.0.0.1:6379> set views 0 OK 127.0.0.1:6379> incr view #默认自增1 (integer) 1 127.0.0.1:6379> incr view (integer) 2 127.0.0.1:6379> decr view #默认自减1 (integer) 1 127.0.0.1:6379> decr view (integer) 0 127.0.0.1:6379> incrby views 10 #根据步长自增 (integer) 10 127.0.0.1:6379> incrby views 10 (integer) 20 127.0.0.1:6379> decrby views 5 ##根据步长自减 (integer) 15 127.0.0.1:6379> decrby views 5 (integer) 10 127.0.0.1:6379> decrby views 5 (integer) 5 127.0.0.1:6379> decrby views 5 (integer) 0
字符串范围
27.0.0.1:6379> set name lijie,nihao OK 127.0.0.1:6379> get name "lijie,nihao" 127.0.0.1:6379> getrange name 5 7 #截取 ",ni" 127.0.0.1:6379> getrange name 0 -1 #获取全部字符串,与get name一致 "lijie,nihao" 127.0.0.1:6379> setrange name 0 666 #替换 (integer) 11 127.0.0.1:6379> get name "666ie,nihao" 127.0.0.1:6379> setrange name 0 jiege #替换 (integer) 11 127.0.0.1:6379> get name "jiege,nihao"
127.0.0.1:6379> setex name1 30 lijie2 #(set with expire )设置过期时间 OK 127.0.0.1:6379> ttl name1 (integer) 21 127.0.0.1:6379> ttl name1 (integer) 19 127.0.0.1:6379> setnx name2 lijie22 # set if not exists(不存在则设置) 在分布式锁中经常用到 (integer) 1 127.0.0.1:6379> keys * 1) "name2" 2) "name" 127.0.0.1:6379> setnx name2 lijie223 #若存在,则不创建,也不能修改 (integer) 0 127.0.0.1:6379> get name2 "lijie22"
批量操作:mset 批量set
mget批量get
msetnx (原子性操作)
127.0.0.1:6379> getset name4 lijie (nil) 127.0.0.1:6379> getset name4 lijie "lijie" 127.0.0.1:6379> getset name4 lijie2 "lijie" 127.0.0.1:6379> get name4 "lijie2" 127.0.0.1:6379>
127.0.0.1:6379> MULTI #开启事务 OK 127.0.0.1:6379(TX)> set name1 lijie1 QUEUED 127.0.0.1:6379(TX)> set name2 lijie2 QUEUED 127.0.0.1:6379(TX)> get name2 QUEUED 127.0.0.1:6379(TX)> mset name3 lijie3 name4 lijie4 QUEUED 127.0.0.1:6379(TX)> exec #执行事务 1) OK 2) OK 3) "lijie2" 4) OK
放弃事务
127.0.0.1:6379> keys * 1) "name1" 2) "name4" 3) "name2" 4) "name3" 127.0.0.1:6379> MULTI #开启事务 OK 127.0.0.1:6379(TX)> set name5 lijie5 QUEUED 127.0.0.1:6379(TX)> mset name6 lijie6 name7 lijie7 QUEUED 127.0.0.1:6379(TX)> DISCARD #取消事务 OK 127.0.0.1:6379> KEYS * #取消事务之后,事务队列中的命令都失效 1) "name1" 2) "name4" 3) "name2" 4) "name3"
异常
watch(面试常问),watch是一个乐观锁
正常情况下
127.0.0.1:6379> mset money 50 out 0 OK 127.0.0.1:6379> keys * 1) "out" 2) "money" 127.0.0.1:6379> WATCH money #监听money,加锁 OK 127.0.0.1:6379> MULTI #开启事务 OK 127.0.0.1:6379(TX)> DECRBY money 20 QUEUED 127.0.0.1:6379(TX)> INCRBY out 20 QUEUED 127.0.0.1:6379(TX)> exec #执行事务 1) (integer) 30 2) (integer) 20
若多线程场景下,其他线程对加锁变量进行修改,则此时会发生异常
127.0.0.1:6379> WATCH money OK 127.0.0.1:6379> MULTI OK 127.0.0.1:6379(TX)> DECRBY money 5 QUEUED 127.0.0.1:6379(TX)> INCRBY out 5 QUEUED 127.0.0.1:6379(TX)> exec #此时会发生异常 (nil) 127.0.0.1:6379>
如果发生失败,获取最新值即可
127.0.0.1:6379> UNWATCH #如果发现失败,则先解锁 OK 127.0.0.1:6379> WATCH money #获取最新值,再次监视 select version OK 127.0.0.1:6379> MULTI #开启事务 OK 127.0.0.1:6379(TX)> DECRBY money 100 QUEUED 127.0.0.1:6379(TX)> INCRBY out 100 QUEUED 127.0.0.1:6379(TX)> exec #执行事务:对比监视的值有没有发生变化,如果没有发生变化,则可以执行,若发生变化,则执行失败,自旋锁继续执行 1) (integer) 400 2) (integer) 120 127.0.0.1:6379>
Redis单线程与多线程