基础知识
- redis默认有16个数据库
- select命令切换数据库
- dbsize命令查看数据库大小
- keys * 查看数据库中的所有键
- flushdb 清空当前数据库
- flushall 情况所有数据库
- set 设置key值
- get 获取对应key的value
- exitsts 判断键值是否存在
- move 移除键值
- expire 设置键的过期时间
- ttl 查看键值剩余时间
- type 查看key值得类型
Redis 是单线程的
官方表示,redis是基于内存操作的,所以cpu不是redis的性能瓶颈,redis的性能瓶颈是机器内存以及网络带宽,既然可以使用单线程实现,就使用单线程。
Redis是c语言写的,官方提供的数据是100000+的QPS,完全不必同样是使用key-value的Memecache差。
Redis单线程为什么还这么快?
- 误区1:高性能的服务器一定是多线程的!
- 误区2:多线程(CPU会上下文切换)一定比单线程效率高!
核心:redis是将所有数据全部放在内存中,所以说使用单线程的效率就是最高的,多线程会进行CPU的上下文切换,这个操作是耗时的。对于内存系统来说,如果没有上下文切换效率就是最高的。多次读写都是在一个CPU上,在内存情况下,这就是最佳方案!
Redis的五大基本数据类型
- String(字符串)
127.0.0.1:6379> set key1 v1 //设置key1的值为v1
OK
127.0.0.1:6379> get key1 //获取key1的值
"v1"
127.0.0.1:6379> append key1 hello //向已存在的key中追加内容,如果键不存在则新建key
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> strlen key1 //获取字符串的长度
(integer) 7
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> incr views //实现key的值+1
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> decr views //实现key的值-1
(integer) 0
127.0.0.1:6379> INCRBY views 10 //指定key的增长值
(integer) 10
127.0.0.1:6379> get views
"10"
127.0.0.1:6379> incrby views 10 //指定key的减少值
(integer) 20
127.0.0.1:6379> decrby views 5
(integer) 15
127.0.0.1:6379> set key2 "hello world"
OK
127.0.0.1:6379> get key2
"hello world"
127.0.0.1:6379> GETRANGE key2 0 3 //获取key指定位置之间的内容
"hell"
127.0.0.1:6379> set key3 abcdefg
OK
127.0.0.1:6379> SETRANGE key3 1 xxx //替换指定位置开始的内容
(integer) 7
127.0.0.1:6379> get key3
"axxxefg"
#setex (set with expire) 设置key的过期时间
#setnx (set with not exits) 如果key不存在,再创建key
127.0.0.1:6379> setex key4 30 "redis"
OK
127.0.0.1:6379> ttl key4
(integer) 25
127.0.0.1:6379> setnx mykey redis1
(integer) 1
127.0.0.1:6379> setnx mykey redis2
(integer) 0
#mset 批量设置key
#mget 批量获取key的值
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 //同时设置k1 k2 k3
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"
127.0.0.1:6379> mget k1 k2 k3 //获取 k1 k2 k3的值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k4 v4 k5 v5 //如果key不存在则批量创建 原子性操作,要么全部成功,要么全部失败
(integer) 1
127.0.0.1:6379> keys *
1) "k3"
2) "k1"
3) "k5"
4) "k4"
5) "k2"
127.0.0.1:6379> msetnx k4 v4 k6 v6
(integer) 0
#对象创建
127.0.0.1:6379> set user:1 {name:zhangsan,age:4} //使用json格式字符串保存对象信息
OK
127.0.0.1:6379> get user:1
"{name:zhangsan,age:4}"
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 4 //key的巧妙设计可以实现对象的创建
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "4"
#getset 先获取key再设置key
127.0.0.1:6379> getset db redis //当前key db不存在,所以返回nil,然后再创建key
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongodb //key存在,则先获取值,再重新设置值
"redis"
127.0.0.1:6379> get db
"mongodb"
String类型的使用场景:value除了是字符串还可以是数字!
- 计数器
- 统计数量
- 粉丝数
- 对象缓存存储
- List(列表)
基本的数据类型,列表。redis里面,list可以当成栈、队列、阻塞队列使用。
所以List命令都是l开头的
127.0.0.1:6379> lpush list one //向list头部添加元素
(integer) 1
127.0.0.1:6379> lpush list tow
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1 //获取list中所有元素
1) "three"
2) "tow"
3) "one"
127.0.0.1:6379> rpush list four //向list尾部添加元素
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "tow"
3) "one"
4) "four"
127.0.0.1:6379> lpop list 移除list第一个元素
"three"
127.0.0.1:6379> lrange list 0 -1
1) "tow"
2) "one"
3) "four"
127.0.0.1:6379> rpop list //移除list最后一个元素
"four"
127.0.0.1:6379> lrange list 0 -1
1) "tow"
2) "one"
127.0.0.1:6379> lindex list 1 //获取list中指定位置的元素
"one"
127.0.0.1:6379> lindex list 0
"tow"
#########################################################################################
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lpush list four
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "four"
2) "three"
3) "tow"
4) "one"
127.0.0.1:6379> llen list //获取list的长度
(integer) 4
127.0.0.1:6379> lrem list 1 one //移除list中指定的元素,以及移除数量(1表示移除的元素数量)
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "four"
2) "three"
3) "tow"
#########################################################################################
127.0.0.1:6379> rpush mylist a
(integer) 1
127.0.0.1:6379> rpush mylist b
(integer) 2
127.0.0.1:6379> rpush mylist c
(integer) 3
127.0.0.1:6379> rpush mylist d
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
127.0.0.1:6379> ltrim mylist 1 2 //截取列表,保留mylist中指定位置区间的元素
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "b"
2) "c"
127.0.0.1:6379> lpush mylist one
(integer) 1
127.0.0.1:6379> lpush mylist two
(integer) 2
127.0.0.1:6379> lpush mylist three
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "three"
2) "two"
3) "one"
#########################################################################################
127.0.0.1:6379> rpoplpush mylist myotherlist //移除mylist列表中的尾部元素并添加到myotherlist列表中的头部
"one"
127.0.0.1:6379> lrange mylist 0 -1
1) "three"
2) "two"
127.0.0.1:6379> lrange myotherlist 0 -1
1) "one"
#########################################################################################
127.0.0.1:6379> lset list 0 item
(error) ERR no such key
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 item //设置列表中指定位置的值,(如果列表不存在或者没有指定位置的值,则报错,更新操作)
OK
127.0.0.1:6379> lrange list 0 0
1) "item"
127.0.0.1:6379> lset list 1 other
(error) ERR index out of range
#########################################################################################
127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpush mylist world
(integer) 2
127.0.0.1:6379> LINSERT mylist before world item //向列表中的指定元素的前方或者后方插入元素
(integer) 3
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "item"
3) "world"
小结:
- 它实际上是一个链表,元素的前后,队列的首尾都可以插入元素
- 如果key不存在则新建链表
- 如果key存在则新增内容
- 如果移除了所有的元素,空链表相当于不存在
- 两边插入值或者修改值效率最高,中间元素效率相对低一点
- 消息排队 队列(Lpush、Lpop) 栈(Lpush、Lpop)
- Set(集合)
set中的值是不能重复的
127.0.0.1:6379> sadd myset hello //向set中添加元素
(integer) 1
127.0.0.1:6379> sadd myset world
(integer) 1
127.0.0.1:6379> smembers myset //查看set中的所有元素
1) "world"
2) "hello"
127.0.0.1:6379> SISMEMBER myset hello //判断某一个元素是否存在
(integer) 1
127.0.0.1:6379> SISMEMBER myset hello1
(integer) 0
127.0.0.1:6379> scard myset //获取set中的元素个数
(integer) 2
127.0.0.1:6379> srem myset hello //移除元素
(integer) 1
127.0.0.1:6379> smembers myset
1) "world"
#######################################################################################
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset redis
(integer) 1
127.0.0.1:6379> sadd myset java
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "java"
2) "redis"
3) "world"
4) "hello"
127.0.0.1:6379> SRANDMEMBER myset //随机获取set中的元素
"redis"
127.0.0.1:6379> SRANDMEMBER myset
"world"
127.0.0.1:6379> SRANDMEMBER myset
"redis"
127.0.0.1:6379> SRANDMEMBER myset
"hello"
127.0.0.1:6379> SRANDMEMBER myset
"world"
#######################################################################################
127.0.0.1:6379> spop myset
"world"
127.0.0.1:6379> spop myset //随机删除set中的元素
"hello"
127.0.0.1:6379> smembers myset
1) "java"
2) "redis"
#######################################################################################
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset world
(integer) 1
127.0.0.1:6379> sadd myset2 redis
(integer) 1
127.0.0.1:6379> smove myset myset2 hello 将指定元素移动到另一个set中
(integer) 1
数字类集合:
- 差集
- 并集
- 交集
127.0.0.1:6379> sadd key1 a
(integer) 1
127.0.0.1:6379> sadd key1 b
(integer) 1
127.0.0.1:6379> sadd key1 c
(integer) 1
127.0.0.1:6379> sadd key2 c
(integer) 1
127.0.0.1:6379> sadd key2 d
(integer) 1
127.0.0.1:6379> sadd key2 e
(integer) 1
127.0.0.1:6379> SDIFF key1 key2 //差集
1) "a"
2) "b"
127.0.0.1:6379> sinter key1 key2 //交集 共同好友可以实现
1) "c"
127.0.0.1:6379> sunion key1 key2 并集
1) "a"
2) "b"
3) "c"
- Hash(哈希)
Map集合(key-map)
127.0.0.1:6379> hset myhash field1 zhangsan //向hash中添加元素
(integer) 1
127.0.0.1:6379> hget myhash field1 //获取hash中指定字段的值
"zhangsan"
127.0.0.1:6379> hmset myhash field1 lisi field2 wangwu //批量添加元素
OK
127.0.0.1:6379> hmget myhash field1 field2 //批量获取元素
1) "lisi"
2) "wangwu"
127.0.0.1:6379> hgetall myhash //获取hash中全部元素
1) "field1"
2) "lisi"
3) "field2"
4) "wangwu"
127.0.0.1:6379> hdel myhash field1 //删除指定元素
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "wangwu"
127.0.0.1:6379> hlen myhash //获取hash字段数量
(integer) 1
127.0.0.1:6379> hkeys myhash //只获取所有字段
1) "field2"
127.0.0.1:6379> hvals myhash //只获取所有字段的值
1) "wangwu"
127.0.0.1:6379> hset myhash field3 5
(integer) 1
127.0.0.1:6379> HINCRBY myhash field3 1 //hash中指定元素的值增加值
(integer) 6
127.0.0.1:6379> HINCRBY myhash field3 -1 //hash中指定元素的值减少值
(integer) 5
127.0.0.1:6379> hsetnx myhash field4 hello //判断hash中是否存在key,如果不存在则创建key,存在则创建失败
(integer) 1
127.0.0.1:6379> hsetnx myhash field4 world
(integer) 0
#########################################################################################
#hash更适合存储对象
127.0.0.1:6379> hmset user:1 name zhangsan age 4 sex 0
OK
127.0.0.1:6379> hgetall user:1
1) "name"
2) "zhangsan"
3) "age"
4) "4"
5) "sex"
6) "0"
127.0.0.1
- Zset(有序集合)
127.0.0.1:6379> zadd myset 1 one //向set中的指定位置添加元素
(integer) 1
127.0.0.1:6379> zadd myset 2 two
(integer) 1
127.0.0.1:6379> zadd myset 3 three
(integer) 1
127.0.0.1:6379> ZRANGE myset 0 -1 //获取set中所有元素
1) "one"
2) "two"
3) "three"
#######################################################################################
#排序
127.0.0.1:6379> zadd salary 6000 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 5000 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 10000 lisi
(integer) 1
127.0.0.1:6379> zadd salary 4000 wangwu
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf //根据score来进行排序 (-inf +inf 从小到大)
1) "wangwu"
2) "zhangsan"
3) "xiaohong"
4) "lisi"
127.0.0.1:6379> ZREM salary xiaohong //移除元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "wangwu"
2) "zhangsan"
3) "lisi"
127.0.0.1:6379> ZCARD salary //查询元素个数
(integer) 3
案例思路:
- 成绩排序,工资排序
- 带权重进行判断
- 排行榜应用