Redis能干嘛
- Redis 官方数据 11W/秒读,8W/秒写,效率高
- 周期性的将数据写入磁盘做持久化。有两种方式:RDB、AOF
- 发布订阅系统,可以做消息队列
- 地图信息分析
- 计时器、计数器(浏览量)
特性
- 多样的数据类型
- 持久化
- 集群
- 事务
Redis基础知识
-
Redis默认有16个数据库 ,默认第0个数据库,可以使用Select 命令切换 ;DBSize可以查看数据库大小; Keys * 可以查看所有的Key;flushall 清除全部 flushdb清除当前库
-
Redis是单线程的
Redis是很快的,Redis是基于内存操作的,CPU不是Redis性能瓶颈Redis的瓶颈是根据机器内存和网络带宽。既然可以使用单线程来实现,所以就使用了单线程。
-
Redis为什么单线程还这么快
-
误区1:高性能的服务器一定是多线程
-
误区2:多线程(CPU上下文切换!)一定比单线程快
CPU速度>内存速度>硬盘速度
核心:Redis是将所有的数据全部放在内存中的,所以说使用单线程操作效率就是最高的。多线程(上下文切换:操作耗时!!),对于内存系统来说,如果没有上下文切换效率就是最高的!多次读写都是在一个CPU上。
-
-
Redis 可以用作数据库,缓存,消息中间件
Redis-Key
String
keys * #查看所有key
Set name Wayne #存值
get name #取值
EXISTS name #检查name是否存在
move name #移除当前key
EXPIRE name 10 #设置过期时间,单位是秒
TTL name # 查看key的剩余时间
Type name # 查看类型
FlushALL #清空所有库
Append Name Zhang #追加字符串
################################################
incr views # views++
decr views # views--
incrby views 10 #views+10
decrby views 10 #views-10
################################################
# setex 设置 key 多长时间过期
127.0.0.1:6379> setex cookie 30 username1
OK
127.0.0.1:6379> get cookie
"username1"
127.0.0.1:6379> ttl cookie
(integer) 22
127.0.0.1:6379> ttl cookie
(integer) 18
127.0.0.1:6379>
#setnx 如果没有才设置,有了就不设置了 (在分布式锁中会用)
127.0.0.1:6379> setnx ok ok
(integer) 1
127.0.0.1:6379> setnx ok notok
(integer) 0
127.0.0.1:6379> get ok
################################################
# mset 批量设置值
# mget 批量获取值
# msetnx 批量存值(如果有已经存在的,全不改)一起成功,一起失败
127.0.0.1:6379> mset k1 v1 k2 v2
OK
127.0.0.1:6379> mget k1 k2
1) "v1"
2) "v2"
127.0.0.1:6379> msetnx k4 v4 k1 v1
(integer) 0
127.0.0.1:6379> get v4
(nil)
127.0.0.1:6379> msetnx k4 v4 k1 v2
(integer) 0
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> get k1
"v1"
################################################
# user:{id}:{filed}
################################################
#getset 先获取一个值在set一个值
127.0.0.1:6379> getset db redis
(nil)
127.0.0.1:6379> getset db mongodb
"redis"
127.0.0.1:6379> get db
"mongodb"
127.0.0.1:6379>
String类型使用场景:Value除了是我们的字符串还可以是数字。
-
计数器
-
对象缓存存储
List
在Redis里面,我们可以把list完成栈、队列、阻塞队列
################################################
# lpush ,从左面push lrange ,取数组 0,-1 取所有 ,rpush,从右面push
127.0.0.1:6379> lpush list1 1 2 3 4 5
(integer) 5
127.0.0.1:6379> lrange list 0 -1
(empty list or set)
127.0.0.1:6379> lrange list1 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
127.0.0.1:6379> rpush list1 1 2 3 4 5
(integer) 10
127.0.0.1:6379> lrange list1 0 -1
1) "5"
2) "4"
3) "3"
4) "2"
5) "1"
6) "1"
7) "2"
8) "3"
9) "4"
10) "5"
################################################
# lpop 从左面移除 rpop从右面移除
127.0.0.1:6379> lpop list1
"5"
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "1"
6) "2"
7) "3"
8) "4"
9) "5"
127.0.0.1:6379> rpop list1
"5"
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "1"
6) "2"
7) "3"
8) "4"
################################################
# llen 获取列表长度
127.0.0.1:6379> llen list1
(integer) 8
################################################
# lrem 移除指定的值
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "1"
6) "2"
7) "3"
8) "4"
127.0.0.1:6379> lrem list -1 4
(integer) 0
127.0.0.1:6379> lrange list1 0 -1
1) "4"
2) "3"
3) "2"
4) "1"
5) "1"
6) "2"
7) "3"
8) "4"
127.0.0.1:6379> lrem list1 10000 4
(integer) 2
127.0.0.1:6379> lrange list1 0 -1
1) "3"
2) "2"
3) "1"
4) "1"
5) "2"
6) "3"
################################################
#rpoplpush
127.0.0.1:6379> lrange list1 0 -1
1) "3"
2) "2"
3) "1"
4) "1"
5) "2"
6) "3"
127.0.0.1:6379> rpoplpush list1 list2
"3"
127.0.0.1:6379> lrange list1 0 -1
1) "3"
2) "2"
3) "1"
4) "1"
5) "2"
127.0.0.1:6379> lrange list2 0 -1
1) "3"
################################################
#lset 更新值,不存在的index,就报超出索引的err了
127.0.0.1:6379> lpush list3 1
(integer) 1
127.0.0.1:6379> lset list3 1 2
(error) ERR index out of range
################################################
#linsert
127.0.0.1:6379> lpush list1 1 2 3
(integer) 3
127.0.0.1:6379> linsert list1 after 2 100
(integer) 4
127.0.0.1:6379> lrange list1 0 -1
1) "3"
2) "2"
3) "100"
4) "1"
################################################
#trim 修剪,有点像SubString
127.0.0.1:6379> lrange list1 0 -1
1) "3"
2) "2"
3) "100"
4) "1"
127.0.0.1:6379> ltrim list1 2 3
OK
127.0.0.1:6379> lrange list1 0 -1
1) "100"
2) "1"
小结
- List实际是链表,Before Node after ,left right 都可以插入值
- 如果key不存在,创建新的链表
- 如果key存在,新增内容
- 如果移除了所有值,空链表,也相当于不存在
- 在两边插入或者改动效率最高,中间元素效率相对来说低
消息队列 Lpush Rpop
栈 Lpush Lpop
Set(集合)
set中的值不能重复
################################################
# sadd 添加 ,sismember 检查是否包含, scard 集合个数,smembers 显示所有成员,srem删除成员,sranmember 随机抽出一个数
127.0.0.1:6379> sadd myset 1
(integer) 1
127.0.0.1:6379> sadd myset 2
(integer) 1
127.0.0.1:6379> sadd myset 3
(integer) 1
127.0.0.1:6379> sismember myset 3
(integer) 1
127.0.0.1:6379> sismember myset 5
(integer) 0
127.0.0.1:6379> sadd myset 3
(integer) 0
127.0.0.1:6379> scard myset
(integer) 3
127.0.0.1:6379> smembers myset
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> srem myset 2
(integer) 1
127.0.0.1:6379> smembers myset
1) "1"
2) "3"
127.0.0.1:6379> smembers myset
1) "1"
2) "3"
127.0.0.1:6379> sadd myset 1 2 3 4 5 6 7
(integer) 5
127.0.0.1:6379> smembers myset
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
127.0.0.1:6379> srandmember myset
"6"
127.0.0.1:6379> srandmember myset 2
1) "6"
2) "4"
################################################
#sdiff 取 差集
#sunion取 并集
#sinter取 交集
127.0.0.1:6379> sadd k1 a b c d e
(integer) 5
127.0.0.1:6379> sadd k2 b c
(integer) 2
127.0.0.1:6379> sdiff k1 k2
1) "a"
2) "d"
3) "e"
127.0.0.1:6379> smembers k1
1) "b"
2) "a"
3) "d"
4) "c"
5) "e"
127.0.0.1:6379> sadd k2 f
(integer) 1
127.0.0.1:6379> sunion k1 k2
1) "d"
2) "c"
3) "b"
4) "a"
5) "f"
6) "e"
127.0.0.1:6379> sinter k1 k2
1) "b"
2) "c"
hash (哈希)
Map集合,key—map。本质和String没有太大区别
################################################
#hset , hmset ,hget ,hmget ,hgetall ,hdel , hlen
127.0.0.1:6379> hset myhash field1 hello
(integer) 1
127.0.0.1:6379> hmset key myhash f2 v2 f3 v3
(error) ERR wrong number of arguments for HMSET
127.0.0.1:6379> hmset myhash f2 v2 f3 v3
OK
127.0.0.1:6379> hget myhash f2
"v2"
127.0.0.1:6379> hmget f2 f3
1) (nil)
127.0.0.1:6379> hmget myhash f2 f3
1) "v2"
2) "v3"
127.0.0.1:6379> hmget myhash f2 f2
1) "v2"
2) "v2"
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "f2"
4) "v2"
5) "f3"
6) "v3"
127.0.0.1:6379> hdel myhash f2
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "f3"
4) "v3"
127.0.0.1:6379> hlen myhash
(integer) 2
################################################
#HEXISTS
127.0.0.1:6379> HEXISTS myhash f3
(integer) 1
################################################
#hkeys hvals 获取所有key 获取vals
127.0.0.1:6379> hkeys myhash
1) "field1"
2) "f3"
127.0.0.1:6379> hvals myhash
1) "hello"
2) "v3"
################################################
#Hincr Hincrby Hdecr Hdecrby
ZSet(有序集合)
在Set的基础上,增加了一个值,用来排序
################################################
#zadd zadd zrange
127.0.0.1:6379> zadd zs 1 xiaotang
(integer) 1
127.0.0.1:6379> zadd zs 2 xiaona 3 zzy
(integer) 2
127.0.0.1:6379> zcard zs
(integer) 3
127.0.0.1:6379> zrange zs 0 -1
1) "xiaotang"
2) "xiaona"
3) "zzy"
################################################
#zrangebyscore 升序排序
127.0.0.1:6379> zrangebyscore zs -inf +inf withscores
1) "xiaotang"
2) "1"
3) "xiaona"
4) "2"
5) "zzy"
6) "3"
#zrevrangebyscore 降序排序 zrevrange
127.0.0.1:6379> zrevrangebyscore zs +inf -inf withscores
1) "zzy"
2) "3"
3) "xiaona"
4) "2"
5) "xiaotang"
6) "1"
127.0.0.1:6379> zrevrange zs 0 -1
1) "zzy"
2) "xiaona"
3) "xiaotang"
################################################
# count 取一共有几个(1<=count<=3)
127.0.0.1:6379> zcount zs 1 3
(integer) 3
事务
Redis单条命令保证原子性,但事务不保证原子性
Redis事务没有隔离级别的概念
Redis的事务:
- 开启事务 multi
- 命令入队 ...
- 执行事务 exec
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> get k2
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) "v2"
Redis 实现乐观锁
################################################
#正常执行成功
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
127.0.0.1:6379> exec
1) (integer) 80
2) (integer) 20
################################################
# 执行失败 返回nil 多线程修改
# 事务执行完注意解锁
127.0.0.1:6379> watch money out
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> incrby money 20
QUEUED
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> unwatch
OK
视频学习资料:B站 狂神说