redis性能测试
redis-benchmark是随着redis安装,官方自带的一个redis性能测试工具
性能测试工具参数列表
参数 | 描述 | 默认值 |
-h | 指定测试主机地址 | 127.0.0.1 |
-p | 指定被测服务器端口 | 6379 |
-s | 指定服务器socket | |
-c | 指定并发连接数 | 50 |
-n | 指定请求数 | 10000 |
-d | 以字节的形式指定set/get值数据大小 | 2 |
-k | 1=keep alive 0=reconnect | 1 |
-r | set/get/incr 使用随机key,sadd使用随机值 | |
-P | 通过管道传输请求 | 1 |
-q | 强制退出redis。仅显示query/sec值 | |
–csv | 以csv格式输出 | |
-l(L小写) | 生成循环,永久执行测试 | |
-t | 仅运行以逗号分隔的测试命令列表 | |
-I(i大写) | Idle模式。仅打开n个Idle连接并等待 |
测试100并发,10,0000条请求
redis-benchmark -c 100 -n 100000
测试解读
====== GET ======
100000 requests completed in 1.41 seconds #在1.41秒内处理完成100000个请求
100 parallel clients #100个并发客户端发起请求
3 bytes payload #每次传输3个字节的数据
keep alive: 1 #保持一台服务器在线处理请求
host configuration "save": 3600 1 300 100 60 10000
host configuration "appendonly": no
multi-thread: no
Latency by percentile distribution:
0.000% <= 0.471 milliseconds (cumulative count 1)
50.000% <= 1.031 milliseconds (cumulative count 50963) #在1.031秒的时候完成50%的请求,已处理请求数量50963
75.000% <= 1.247 milliseconds (cumulative count 75531)
87.500% <= 1.415 milliseconds (cumulative count 87734)
93.750% <= 1.575 milliseconds (cumulative count 93767)
96.875% <= 1.735 milliseconds (cumulative count 96968)
98.438% <= 1.887 milliseconds (cumulative count 98449)
99.219% <= 2.023 milliseconds (cumulative count 99233)
99.609% <= 2.167 milliseconds (cumulative count 99617)
99.805% <= 2.287 milliseconds (cumulative count 99808)
99.902% <= 2.383 milliseconds (cumulative count 99905)
99.951% <= 2.503 milliseconds (cumulative count 99952)
99.976% <= 2.647 milliseconds (cumulative count 99976)
99.988% <= 2.799 milliseconds (cumulative count 99988)
99.994% <= 2.871 milliseconds (cumulative count 99994)
99.997% <= 2.903 milliseconds (cumulative count 99997)
99.998% <= 2.927 milliseconds (cumulative count 99999)
99.999% <= 2.943 milliseconds (cumulative count 100000)
100.000% <= 2.943 milliseconds (cumulative count 100000)
Cumulative distribution of latencies:
0.000% <= 0.103 milliseconds (cumulative count 0)
0.094% <= 0.503 milliseconds (cumulative count 94)
3.190% <= 0.607 milliseconds (cumulative count 3190)
10.049% <= 0.703 milliseconds (cumulative count 10049)
21.096% <= 0.807 milliseconds (cumulative count 21096)
33.435% <= 0.903 milliseconds (cumulative count 33435)
47.700% <= 1.007 milliseconds (cumulative count 47700)
60.244% <= 1.103 milliseconds (cumulative count 60244)
71.778% <= 1.207 milliseconds (cumulative count 71778)
80.330% <= 1.303 milliseconds (cumulative count 80330)
87.321% <= 1.407 milliseconds (cumulative count 87321)
91.495% <= 1.503 milliseconds (cumulative count 91495)
94.587% <= 1.607 milliseconds (cumulative count 94587)
96.487% <= 1.703 milliseconds (cumulative count 96487)
97.791% <= 1.807 milliseconds (cumulative count 97791)
98.555% <= 1.903 milliseconds (cumulative count 98555)
99.165% <= 2.007 milliseconds (cumulative count 99165)
99.472% <= 2.103 milliseconds (cumulative count 99472)
100.000% <= 3.103 milliseconds (cumulative count 100000)
Summary:
throughput summary: 70771.41 requests per second #每秒钟处理70771.41个请求
latency summary (msec):
avg min p50 p95 p99 max
1.064 0.464 1.031 1.631 1.983 2.943
基础知识
redis默认有16个数据库,默认使用第0个数据库,redis可以用作数据库、缓存、和队列
- 使用命令
select
切换数据库 -
dbsize
显示当前数据库大小(也就是当前选中的数据库存在多少个key) -
keys *
查看当前数据库所有的key -
flushall
清空所有的数据库 -
flushdb
清空当前数据库
redis5以及之前的版本都是单线程的,redis6以及之后的版本开始支持多线程。redis不受cpu瓶颈限制,性能关乎网络带宽和内存
关于Key的基本命令
判断某个键是否存在
127.0.0.1:6379> exists age
(integer) 1
127.0.0.1:6379> exists age1
(integer) 0
移动某个键到指定的数据库
127.0.0.1:6379> move age 1
# 1表示指定的数据库index
(integer) 1
删除键
del key
设置过期时间
为一个键设置过期时间,时间一到,该键自动过期无法再获得
expire 键 过期时间(秒)
-
ttl 键名
查看该键的距离过期还剩余的时间
查看键的类型
type 键名
五大数据类型
String类型
redis中的字符串类型可以动态进行修改,可以使用追加命令在字符串值的后面直接追加内容。返回追加之后的字符串长度
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> keys *
1) "k1"
2) "name"
127.0.0.1:6379> exists k1
(integer) 1
127.0.0.1:6379> append k1 zhong
(integer) 7
127.0.0.1:6379> get k1
"v1zhong"
strlen key
获取字符串长度
127.0.0.1:6379> strlen k1
(integer) 7
append key value
如果过追加的key不存在就相当于直接set一个key
自增和自减
incr key
让键自增1,decr key
让键自减1
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> decr view
(integer) 0
incrby key step
和decrby key step
指定步长的自增和自减,指定的步长只会在本条命令下生效,不会影响其他的命令的步长
127.0.0.1:6379> incrby views 10
(integer) 11
127.0.0.1:6379> incr views
(integer) 12
127.0.0.1:6379> decrby views 10
(integer) 2
查看字符串指定范围
getrange key start end
可以查看一个字符串的指定范围,也就是某一个字符的下标到某一个字符的下标(闭区间),end位如果是**-1**就表示一直到这个字符串的末尾。
127.0.0.1:6379> set k1 hello
OK
127.0.0.1:6379> get k1
"hello"
127.0.0.1:6379> getrange k1 0 3
"hell"
127.0.0.1:6379> getrange k1 0 -1
"hello"
替换字符串指定位置的字符
可以通过setrange key offset value
命令替换字符串中指定起始下标的字符。
127.0.0.1:6379> set k2 abcdefg
OK
127.0.0.1:6379> get k2
"abcdefg"
127.0.0.1:6379> setrange k2 1 xx #替换该字符串中下标为1以及之后的字符,指定替换内容为xx,类似于insert模式
(integer) 7
127.0.0.1:6379> get k2
"axxdefg"
127.0.0.1:6379>
设置键的同时指定过期时间
通过setex key seconde value
新建键的同时为这个键设置过期时间。
127.0.0.1:6379> setex k3 30 zhong
OK
127.0.0.1:6379> ttl k3
(integer) 27
127.0.0.1:6379> ttl k3
(integer) -2
127.0.0.1:6379> get k3
(nil)
不存在的情况下新建键
在新建一个键的同时判断是否存在同名的键,存在同名的键则不会执行新建操作,也就是说不会出现覆盖原来的value的情况
127.0.0.1:6379> setnx k3 zhong
(integer) 1
127.0.0.1:6379> setnx k3 zhong2
(integer) 0
127.0.0.1:6379> get k3
"zhong"
批量获取值和设置值
通过mset
和mget
批量设置和获取值
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"
msetnx
redis的事务可以不是原子性操作,但是命令msetnx
是一个原子性操作,他批量设置的值一起成功或者一起失败
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"
127.0.0.1:6379> msetnx k1 v1 k4 v4
(integer) 0
127.0.0.1:6379> get k4
(nil)
可以看见新建键k4失败了,是因为k1键已经存在了,导致了整个命令都会失败
redis key 命名规范 键名称中的冒号 : 命名空间层次的表示
redis由于是kv键值对的方式存储数据,那对于一些有关系的某一类的数据直接存储会显得比较杂乱,于是出现这种key的命名规范(使用:表示层次,称作命名空间),这种key的命名方式能够让人一眼就能看出哪些key之间是存在联系的。但是redis本身是没有对冒号:做任何特殊处理的,类似这样使用命名空间的key会被整个当成string处理,也就是说key的名字就是keyname:name1:name2
。通过keys *
可以清楚的看出这一点
127.0.0.1:6379> set user:1:name zhong
OK
127.0.0.1:6379> set user:1:age 2
OK
127.0.0.1:6379> keys *
1) "user:1:age"
2) "k2"
3) "user:1:name"
4) "k1"
5) "k3"
组合命令
在redis中存在组合式的命令,例如getset key value
,redis会先取该键的值然后再对该键写入新的value
list
list可以被用作栈和队列,所有的list命令都以字母l开头
添加元素
命令lpush key value
添加元素。lpush的全程是left-push(左插入,头插法),可以把list想象成一个左右开口的队列,我们既可以从左边插入元素(也就是头),也可以从右边插入元素(也就是尾)。
127.0.0.1:6379> lpush list 1
(integer) 1
rpush key value
的全称是right-push(右插入,尾插法)
127.0.0.1:6379> rpush list 4
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "3"
2) "2"
3) "1"
4) "0"
5) "4"
获取指定下标范围的value
lrange key start end
,因为lpush类似于入栈操作,于是最后一个入栈的元素下标才为0
127.0.0.1:6379> lrange list 0 -1
1) "3"
2) "2"
3) "1"
弹出元素
命令lpop key
和rpop key
左弹出元素和右弹出元素
127.0.0.1:6379> lpop list
"3"
127.0.0.1:6379> rpop list
"4"
获取指定下标的元素
lindex key index
127.0.0.1:6379> lindex list 1
"1"
获取list的长度
llen key
返回列表的长度
127.0.0.1:6379> llen list
(integer) 3
移除指定元素
lrem key count value
可以指定移除某个元素并且可以移除多个
127.0.0.1:6379> lpush list 1
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "1"
2) "2"
3) "1"
4) "0"
127.0.0.1:6379> lrem list 2 1 #移除2次元素“1”
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "2"
2) "0"
截取指定区间的元素
ltrim key strat end
截取指定区间的元素,该明令会保留指定区间中的元素,不在区间中的元素会被删除
127.0.0.1:6379> lpush list hello hello1 hello2 hello3
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "hello3"
2) "hello2"
3) "hello1"
4) "hello"
127.0.0.1:6379> ltrim list 1 2
OK
127.0.0.1:6379> lrange list 0 -1
1) "hello2"
2) "hello1"
组合命令rpoplpush
rpoplpush key1 key2
可以将一个list中的元素又弹出并且左压入一个新的list
127.0.0.1:6379> lrange list 0 -1
1) "hello2"
2) "hello1"
127.0.0.1:6379> rpoplpush list list2
"hello1"
127.0.0.1:6379> rpoplpush list list2
"hello2"
127.0.0.1:6379> rpoplpush list2 list2
"hello1"
lset
lset key index value
命令可以更新list中指定下标位置的元素,前提是,这个list已经被创建出来了,并且对应被更新下标的值存在。
插入语句
linsert key before|after value value
可以指定插入到list中某个元素的前后
127.0.0.1:6379> lrange list2 0 -1
1) "hello1"
2) "hello2"
127.0.0.1:6379> linsert list2 before "hello2" "i"
(integer) 3
127.0.0.1:6379> lrange list2 0 -1
1) "hello1"
2) "i"
3) "hello2"
set(集合)
set中的value是不会重复的
添加元素
sadd key value
127.0.0.1:6379> sadd set hello
(integer) 1
127.0.0.1:6379> sadd set hello1 hello2 hello3
(integer) 3
查看集合中的元素
smembers key
127.0.0.1:6379> smembers set
1) "hello2"
2) "hello"
3) "hello3"
4) "hello1"
判断某个元素是否存在集合中
sismember key value
127.0.0.1:6379> sismember set hello
(integer) 1
127.0.0.1:6379> sismember set hello6
(integer) 0
获取set长度
scard key
127.0.0.1:6379> scard set
(integer) 4
移除集合中的某个元素
srem key value
127.0.0.1:6379> smembers set
1) "hello"
2) "hello2"
3) "hello1"
4) "hello3"
127.0.0.1:6379> srem set hello3
(integer) 1
127.0.0.1:6379> smembers set
1) "hello"
2) "hello2"
3) "hello1"
随机给出某个set中的元素
srandmembers key [随机给出的元素个数]
127.0.0.1:6379> srandmember set
"hello"
127.0.0.1:6379> srandmember set
"hello1"
随机弹出元素
由于set是无序集合,于是弹出元素也是随机的spop key
127.0.0.1:6379> spop set
"hello1"
移动set元素
将一个set中的某个值移动到另一个set中smove source 目标set value
127.0.0.1:6379> sadd set1 hello hello1 hello2
(integer) 3
127.0.0.1:6379> sadd set2 zhong
(integer) 1
127.0.0.1:6379> smove set1 set2 hello
(integer) 1
127.0.0.1:6379> smembers set1
1) "hello2"
2) "hello1"
127.0.0.1:6379> smembers set2
1) "hello"
2) "zhong"
集合之间的运算
差集
sdiff key key
127.0.0.1:6379> sadd set1 a b c
(integer) 3
127.0.0.1:6379> sadd set2 c d e
(integer) 3
127.0.0.1:6379> sdiff set1 set2
1) "a"
2) "b"
并集
sinter key key
127.0.0.1:6379> sunion set1 set2
1) "e"
2) "b"
3) "c"
4) "a"
5) "d"
交集
sunion key key
127.0.0.1:6379> sinter set1 set2
1) "c"
Hash
哈希类型类似map类型,或者说像json类型,在redis中普遍都是kv键值对,但是hash类型的值也是一种键值对。key这样的类型
添加元素
hset key field value
,在hash类中存在字段这个概念,我们需要通过具体的字段名来找到一个值。同时这个命令本身也支持同时存储多个字段
127.0.0.1:6379> hset hash field zhong
(integer) 1
获取元素
hget key field
我们需要知道获取哪个hash的的具体哪一个字段
127.0.0.1:6379> hget hash field
"zhong"
批量获取
hmget key field...
批量获取多个字段中的值
127.0.0.1:6379> hmget hash field1 field2 field3
1) "1"
2) "2"
3) "3"
获取所有字段
获取所有的字段和值
127.0.0.1:6379> hgetall hash
1) "field1"
2) "1"
3) "field2"
4) "2"
5) "field3"
6) "3"
删除字段
hdel key field
删除字段
127.0.0.1:6379> hdel hash field3
(integer) 1
获取长度
127.0.0.1:6379> hlen hash
(integer) 2
只获取所有字段或者值
127.0.0.1:6379> hkeys hash
1) "field1"
2) "field2"
127.0.0.1:6379> hvals hash
1) "1"
2) "2"
自增和自减
127.0.0.1:6379> hincrby hash field1 5
(integer) 6
127.0.0.1:6379> hincrby hash field1 -1
(integer) 5
存在创建
当字段不存在才会创建值
127.0.0.1:6379> hsetnx hash field1 2
(integer) 0
Zset(有序集合)
保证了元素的唯一性,并且通过设置score字段将集合内的元素排序。这个字段本身并不属于key或者value,它只是标记了该key
添加元素
127.0.0.1:6379> zadd zset 1 one
(integer) 1
127.0.0.1:6379> zadd zset 2 two 3 three
(integer) 1
获取zset内的元素
127.0.0.1:6379> zrange zset 0 -1
1) "one"
2) "two"
3) "three"
通过排序获取元素
通过这种排序获得的元素始终现实为升序
127.0.0.1:6379> zrangebyscore salary -inf +inf
1) "ming"
2) "zhong"
3) "zhang"
降序命令
127.0.0.1:6379> zrevrangebyscore salary +inf -inf
1) "zhang"
2) "zhong"
3) "ming"
参数withscores,同时现实score字段值
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores
1) "ming"
2) "2000"
3) "zhong"
4) "2000"
5) "zhang"
6) "5000"
移除元素
127.0.0.1:6379> zrem salary ming
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores
1) "zhong"
2) "2000"
3) "zhang"
4) "5000"
获取有序集合中的个数
127.0.0.1:6379> zcard salary
(integer) 2
获取指定区间的成员数量
指定区间是通过score表示
127.0.0.1:6379> zadd set 1 zhong 2 zhang 3 hello
(integer) 3
127.0.0.1:6379> zcount set 1 2 #表示获取score在1到2中的元素
(integer) 2