Redis基本介绍
redis-benchmark性能测试工具
测试如:
redis-benchmark -h localhost -p 6379 -c 100 -n 10000000
redis默认有16个数据库
切换数据库和查看数据库大小 :
设置值和取值:
>set name chunling
>get name
>keys * #查看当前数据库所有的key
清空数据库:
flushdb #清空当前数据库的内容
FLUSHALL #清空全部数据库的内容
Redis是单线程的:
Redis是基于内存操作的,CPU不是Redis性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽,单线程实现就很快了,所以就用单线程。
Redis是C语言写的,官方提供的数据为10w+的QPS,完全不比同样实验key-value的Memecache差!
Redis单线程的为什么还那么快?
误区1:高性能的服务器一定是多线程的?
误区2:多线程(CPU上下文会切换!)一定比单线程效率高
redis是将所有数据都存放在内存中,所以说使用单线程去操作效率就算最高的,多线程(CPU上下文会切换,耗时耗资源),对于内存系统来说,如果没有上下文切换效率就算最高的!多次读写都是在一个CPU上的,在内存情况这个就算最佳方案
设置过期时间
>expire name 10 #变量name10秒后过期
>ttl name #查看还要几秒过期
>exists name #判断当前的key是否存在
>move name 1 #移除当前的key
>type name #查看当前key的type
=========================================================================
五大数据类型
String类型
set,get,keys*, append,exists
127.0.0.1:6379> set key1 v1
OK
127.0.0.1:6379> get key1
"v1"
127.0.0.1:6379> keys *
1) "key1"
127.0.0.1:6379> exists key1
(integer) 1
127.0.0.1:6379> append key1 "hello" #在key1末尾增加字符串"hello"
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> strlen key1 #返回的是key1的长度
(integer) 7
应用,一些文章尾部的浏览量,incr,decr,incrby(设置步长,指定增量),decrby
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> incr views
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> incr views
(integer) 3
127.0.0.1:6379> decr views
(integer) 2
127.0.0.1:6379>
127.0.0.1:6379> decr views
(integer) 1
127.0.0.1:6379> incrby views 10
(integer) 11
127.0.0.1:6379> incrby views 10
(integer) 21
127.0.0.1:6379> decrby views 3
(integer) 18
127.0.0.1:6379> decrby views 3
(integer) 15
截取字符串和替换字符串
127.0.0.1:6379> set key1 "hello,my friend!"
OK
127.0.0.1:6379> get key1
"hello,my friend!"
127.0.0.1:6379> getrange key1 0 3
"hell"
127.0.0.1:6379> getrange key1 0 -1
"hello,my friend!"
127.0.0.1:6379> set key2 abcdefg
OK
127.0.0.1:6379> get key2
"abcdefg"
127.0.0.1:6379> setrange key2 1 xxcd
(integer) 7
127.0.0.1:6379> get key2
"axxcdfg"
setex设置过期时间
setnx如果不存在就创建会返回1,否则会返回0(分布式锁常用)
127.0.0.1:6379> setex key3 30 "hellllo"
OK
127.0.0.1:6379> ttl key3
(integer) 22
127.0.0.1:6379> get key3
"hellllo"
127.0.0.1:6379> setnx mykey "redis" #1说明创建成功
(integer) 1
127.0.0.1:6379> get mykey
"redis"
127.0.0.1:6379> setnx mykey "eeeee" #0说明创建失败,因为重复命名了
(integer) 0
127.0.0.1:6379> get mykey
"redis"
127.0.0.1:6379> get key3
(nil)
127.0.0.1:6379> ttl key3 #-2说明已经过期了
(integer) -2
mset,mget是原子性的操作,要么一起成功要么一起失败
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v1 k4 v4
(integer) 0
创建对象
方式一set:设置一个user:1 对象 值为json字符
方式二mset:user:{id}:{field} value user:{id}:{field} value
127.0.0.1:6379> clear
127.0.0.1:6379> set user:1{name:zhangsan,age:3}
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> set user:1 {name:zhangsan,age:3}
OK
127.0.0.1:6379> get user
(nil)
127.0.0.1:6379> get user:1
"{name:zhangsan,age:3}"
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "2"
127.0.0.1:6379>
getset 先get 没有找到再set
127.0.0.1:6379> getset db redis
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongodb
"redis"
127.0.0.1:6379> get db
"mongodb"
数据结构是相通的!
String类似使用场景:value除了是字符串还可以是我们的数字!
如:计数器,统计多单位的数量(如粉丝数自增,uid:xxx follower 0 incr)
List列表
把list看成双向队列,lpush和 rpush,lpop和rpop
127.0.0.1:6379> lpush list 1 #依次从头部插入值
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "1"
127.0.0.1:6379> lrange list 0 1
1) "three"
2) "two"
127.0.0.1:6379> rpush list 666 #从尾部插入值
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "1"
4) "666"
127.0.0.1:6379> lpop list #移除头部元素
"three"
127.0.0.1:6379> rpop list #移除尾部元素
"666"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "1"
获取列表长度,获取列表中指定索引的值,移除列表中指定索引的值
127.0.0.1:6379> llen list #列表长度
(integer) 7
127.0.0.1:6379> lrange list 0 -1 #展示列表
1) "1"
2) "1"
3) "1"
4) "5"
5) "4"
6) "two"
7) "1"
127.0.0.1:6379> lindex list 4 #获取索引为4的值,索引从下标0开始
"4"
127.0.0.1:6379> lrem list 2 1 #从列表头部到尾部,依次移除两个1
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "1"
2) "5"
3) "4"
4) "two"
5) "1"
trim修剪列表,rpoplpush弹出原列表最后一个元素并将它移动到新列表中
127.0.0.1:6379> ltrim list 1 3 #只保留列表下标为1到3的值
OK
127.0.0.1:6379> lrange list 0 -1
1) "5"
2) "4"
3) "two"
127.0.0.1:6379> rpoplpush list myotherlist #将列表list尾部元素弹出并压入到列表myotherlist头部
"two"
127.0.0.1:6379> lrange list 0 -1
1) "5"
2) "4"
127.0.0.1:6379> lrange myotherlist 0 -1
1) "two"
lset将列表成指定下标的值替换成新值,linsert将某个具体值插入到列表中某个元素的前面或后面
127.0.0.1:6379> lset list 0 77
OK
127.0.0.1:6379> lrange list 0 -1
1) "77"
2) "4"
127.0.0.1:6379> linsert list before 4 newvalue
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "77"
2) "newvalue"
3) "4"
列表总结:
可是链表可是双向队列可是栈,before,after(linsert),left,right(push)都可以插入值,通过下标获取元素lindex,利用列表可以做消息队列(Lpush Rpop),栈(Lpush Lpop)。
Set集合
set是集合元素不可重复
添加元素sadd,展示集合smembers,判断某个元素是不是集合中的元素,获取集合myset内容元素个数scard
127.0.0.1:6379> sadd myset hello #给集合myset添加元素
(integer) 1
127.0.0.1:6379> smembers myset #展示集合
1) "9"
2) "55"
3) "4"
4) "1"
5) "hello"
127.0.0.1:6379> sismember myset hello #查看hello是不是集合中的元素
(integer) 1
127.0.0.1:6379> scard myset
(integer) 4
获取随机元素srandmember,移除原先集合的元素到新集合smove,删除随机元素spop
127.0.0.1:6379> srandmember myset #从集合myset随机抽取一个元素
"hello"
127.0.0.1:6379> srandmember myset
"4"
127.0.0.1:6379> smove myset newset hello #将集合myset的元素hello移动到集合newset
(integer) 1
127.0.0.1:6379> smembers myset
1) "1"
2) "4"
3) "9"
4) "55"
127.0.0.1:6379> smembers newset
1) "hello"
127.0.0.1:6379> smembers myset
1) "44"
2) "4422"
3) "4"
4) "2"
127.0.0.1:6379> spop myset 1 #随机删除1个元素
1) "44"
127.0.0.1:6379> spop myset 2 #随机删除2个元素
1) "2"
2) "4422"
127.0.0.1:6379> smembers myset
1) "4"
交集sinter,并集sunion,差集sdiff(应用:共同好友)
127.0.0.1:6379> sadd set2 a e f
(integer) 3
127.0.0.1:6379> sadd set1 a b c
(integer) 3
127.0.0.1:6379> smembers set1
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> smembers set2
1) "a"
2) "f"
3) "e"
127.0.0.1:6379> sdiff set1 set2 #以set1为基础,求它和set2差集
1) "b"
2) "c"
127.0.0.1:6379> sinter set1 set2 #求set1和set2的交集
1) "a"
127.0.0.1:6379> sunion set1 set2 #求set1和set2的并集
1) "a"
2) "f"
3) "b"
4) "c"
5) "e"
Hash类型
Map集合,key-map,这个值是一个map集合,本质和String类型没有太大区别,还是一个简单的key-value
向哈希表myhash添加(单个/多个)key-value
获取一个字段值/获取多个字段值/获取全部数据
删除myhash指定的key字段
127.0.0.1:6379> hset myhash f1 hello #设置单个key-value
(integer) 1
127.0.0.1:6379> hget myhash f1
"hello"
127.0.0.1:6379> hset myhash f1 hello f2 my f3 friend #设置多个key-value
(integer) 2
127.0.0.1:6379> hgetall myhash #获取myhash所有元素
1) "f1"
2) "hello"
3) "f2"
4) "my"
5) "f3"
6) "friend"
127.0.0.1:6379> hmget myhash f1 f2 #获取myhash多个元素
1) "hello"
2) "my"
127.0.0.1:6379> hdel myhash f1 #获取myhash指定字段。其对应的value也会消失
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "f2"
2) "my"
3) "f3"
4) "friend"
获取hash表的大小hlen,
判断某个属性是否存在hexists
获得所有hkeys/hvals
某属性的数值自增/减hincrby
添加属性值如果不存在返回1,存在返回0 hset
127.0.0.1:6379> hlen myhash
(integer) 2
127.0.0.1:6379> hexists myhash f2
(integer) 1
127.0.0.1:6379> hkeys myhash
1) "f2"
2) "f3"
127.0.0.1:6379> hvals myhash
1) "my"
2) "friend"
127.0.0.1:6379> hset myhash f3 5
(integer) 0
127.0.0.1:6379> hset myhash f1 5
(integer) 1
127.0.0.1:6379> hincrby myhash f1 2
(integer) 7
127.0.0.1:6379> hincrby myhash f1 2
(integer) 9
127.0.0.1:6379> hincrby myhash f1 -3
(integer) 6
127.0.0.1:6379> hsetnx myhash f3 hello
(integer) 0
127.0.0.1:6379> hsetnx myhash f4 hello
(integer) 1
hash变更的数据user name age,尤其是用户信息之类,因此hash更适合于对象的存储,而String更是哈哈字符串的存储
Zset类型
将set中元素按升序查出,按降序查出,按范围筛选查出
127.0.0.1:6379> zadd salary 2500 xiao
(integer) 1
127.0.0.1:6379> zadd salary 500 o
(integer) 1
127.0.0.1:6379> zadd salary 10000 sss
(integer) 1
127.0.0.1:6379> zrangebyscore salary 0 -1
(empty array)
127.0.0.1:6379> zrangebyscore salary -1 0
(empty array)
127.0.0.1:6379> zrangebyscore salary 0 +inf #升序
1) "o"
2) "xiao"
3) "sss"
127.0.0.1:6379> zrevrange salary 0 -1 #降序
1) "sss"
2) "xiao"
3) "o"
127.0.0.1:6379> zrevrange salary 0 -100
(empty array)
127.0.0.1:6379> zrangebyscore salary -1 600 #查找工资在范围-1~600间的
1) "o"
移除有序集合salary指定元素zrem,获取有序集合个数zcard
127.0.0.1:6379> zrem salary xiao
(integer) 1
127.0.0.1:6379> zrevrange salary 0 -1
1) "sss"
2) "o"
127.0.0.1:6379> zcard salary
(integer) 2
获取指定区间内,有序集合myset的元素个数
127.0.0.1:6379> zadd myset 1 hello
(integer) 1
127.0.0.1:6379> zadd myset 2 my 3 friend
(integer) 2
127.0.0.1:6379> zrange myset 0 -1
1) "hello"
2) "my"
3) "friend"
127.0.0.1:6379> zadd myset 0 zz #注意看,设置的分数是0,因此会插入在第一位哦
(integer) 1
127.0.0.1:6379> zrange myset 0 -1
1) "zz"
2) "hello"
3) "my"
4) "friend"
127.0.0.1:6379> zcount myset 1 3 #指定范围的个数
(integer) 3
Zset适合做排行榜