目录
通用命令
keys [parten]
:获得数据库中所有的键--------(O(n),一般不会用)dbsize
:算出key的总数exists key
:判断key是否存在,存在返回1del [key ... ]
:删除多个keyexpire key seconds
:给key设置秒级的过期时间(用在缓存上)ttl key
:查看key的过期时间,-2代表不存在,-1是永远不会过期persist
:去掉的key的过期时间type key
:查看key的数据类型
单线程
多个线程执行命令在Redis上是串行执行的,如下图所示:
为什么Redis单线程这么快?
数据全部放在内存中
(主要原因)- 多路I/O复用模型,非阻塞IO
- 避免线程切换和竟态消耗
多路I/O复用模型
假设你是一个老师,让30个学生解答一道题目,然后检查学生做的是否正确:
你站在讲台上等,谁解答完谁举手
。- 这时C、D举手,表示他们解答问题完毕,你下去依次检查C、D的答案,然后继续回到讲台上等。
- 此时E、A又举手,然后去处理E和A…
单线程需要注意什么?
- 一次只运行一条命令
拒绝长或慢的命令
- 在一些命令下不是单线程
数据结构
Redis主要有5种数据类型,包括String
,List
,Set
,Zset
,Hash
,满足大部分的使用要求。每个数据结构由多种内部编码。
采用这种形式的原因是:内存的空间比较珍贵,采用不同的编码主要应用于不同场景—时间换空间或者空间换时间
数据类型 | 可以存储的值 | 操作 |
---|---|---|
STRING | 字符串、整数、比特或者浮点数 | 对整个字符串或者字符串的其中一部分执行操作 对整数和浮点数执行 自增 或者自减操作 |
HASH | 包含键值对的无序散列表 | 存储对象 |
LIST | 列表 | 从两端压入或者弹出元素 对单个或者多个元素进行修剪 只保留一个范围内的元素 |
SET | 无序集合 | 添加、获取、移除单个元素 检查一个元素是否存在于集合中 计算交集、并集、差集 从集合里面随机获取元素 |
ZSET | 有序集合 | 添加、获取、删除元素 根据分值范围或者成员来获取元素 计算一个键的排名 |
字符串
Redis所有的key 都是字符串,value 分为不同的数据类型,最大为512M,可以存储的值如下所示:
场景
- 缓存
- 计数器
- 分布式锁
- 记录网站访问量
- 缓存视频基本信息
- 分布式id生成器
常用操作
get key
:获取key的值set key value
:设置一组键值对,不管key是否存在setnx key value
:创建一组键值对,当key不存在时才设置set key value xx
:更新一组键值对,当key存在时才设置getset key value
:将旧值覆盖,返回旧值append key value
:在旧值后面追加一个值strlen
:计算字符串长度,注意:中文占两个长度del key
:删除一组键值对incr key
:自增1,如果key不存在,自增后get(key)=1decr key
:自减1,不存在 get(key)=-1incrby key k
:key 自增 k ,key不存在,自增后 get(k)=kdecrby key k
:key自减 k,key不存在 ,自减后 get(key)=-kmset key1 value1 [key2 value2.....]
:批量设置多组键值对-------性能O(n)mget key1 [key2 ......]
:获取多组键值对-------性能O(n)
多次get和mget的差异
- 最主要:网络时间是最大开销
可以发现:<mark>mget时间效率非常高,当然如果数据量非常大,建议分多次获取</mark>
实战1
实现如下功能:
- 记录网站每个用户个人主页的访问量?
实现:
- 设置
用户id为key,访问量为value
- 由于是单线程的情况下,
无竞争
- 每当有个用户访问,使用命令:
incr userid
实战2
实现如下功能:
- 缓存视频的基本信息(数据源在MySQL中)伪代码
实现流程如下:
伪代码如下所示:
实战3
实现如下功能:
- 分布式id生成器,每次获取的id是递增的,如下所示:
思路
- 使用命令:
incr id
hash
键值结构如下所示,field不能相同,value可以相同:
特点
是一个Map<key,Map<key,value>>
的结构,主要用于存储对象
常用操作(与String类似)
hget key field
:获取key对应field的value值hset key field value
:设置key对应field的value值hdel key field
:删除key对应filedhexists key field
:判断key对应field是否存在hlen key
:获取key对应field的个数hmget key field1[ field2 .....]
:获取key对应多个field的value值hmget key field1 value1 [ field2 value2 .....]
:设置key对应多个field的value值hgetall key
:返回key所有的field和value值 ----- (注意使用,性能O(n))hvals key
:返回key所有的value值hkeys key
:返回key所有的field
String VS Hash
相同点
- API类似
不同点
- String保存用户信息,需要使用序列化或者保存多个key
- Hash保存用户信息,每个field对应用户的属性
- 方案比较如下所示:
List
列表的结构如下所示:
特点是:有序、可以重复和可以从左右插入或者弹出
重要API
<mark>时间复杂度都是都是O(n)</mark>
linsert key before|after value new value
:在指定值前(后)插入一个新值----复杂度(O(n))lrem key count value
:根据key删除count个value值。count>0,是从左到右;count <0,是从右到做;count=0,是删除全部ltrim key start end
:只保存索引范围内的数据lrange key start end
:获取列表指定范围的数据lindex key index
:获取指定下标的元素lset key index newvalue
:将制定索引的值修改为newvalue
时间复杂度都是是O(1)
llen key
:获取列表的长度-
rpush key value1 value2.....
:从列表右端插入值
lpush key value1 value2.....
:从列表左端插入值-
lpop key
:从左边弹出一个元素
rpop key
:从右边弹出一个元素blpop key timeout
:从左边弹出,timeout是阻塞时间,如果超时则不执行退出等待,timeout=0时,代表无限等待brpop key timeout
:从右边弹出,timeout是阻塞时间
实战
实现下列功能
- 实现时间轴的功能,如下图所示:
实现思路如下图所示
- 每当有一个新微博发布,利用
lpush key value
插入这个数据 - 具体的数据信息,可以使用
Hash
存储 - 使用命令
lrange key start end
,可以取出部分数据,然后做一个分页的功能
小技巧
Set
数据结构如下图所示,即一个key保存多个字符串:
特点
- 无序
- 无重复
- 支持集合间的操作,如
交集、并集以及差集
重要API
集合内的API
sadd key element
:向集合中添加多个元素srem key element
:删除集合某个元素scard key
:计算集合中的元素个数sismember key element
:判断集合中是否有这个元素srandmember key
:从集合中随机取出一个元素spop key
:从集合中随机弹出一个元素smembers
:从集合中取出全部元素(无序的、可能会阻塞到Redis)
集合间的API
sdiff key1 key2
:计算两个集合中的差集sinter key1 key2
:计算交集sunion key1 key2
:计算并集
实战1
需求
- 完成抽奖的功能,如下图所示:
实现:
- 每当有一个人抽奖,则利用命令
sadd key element
添加至集合 - 最后可以使用
spop
或者srandmember
实现功能
实战2
Zset
数据结构如下图所示,score代表分数,按照分数排序:
集合 VS 有序集合
相同点:
- 集合和有序集合,都
不允许重复元素
不同点:
- 集合是
无序
的,有序集合是有序
的 - 集合是只有
element
,有序集合是element+score
列表 VS 有序集合
相同点
- 都是有序的
不同点
- 列表是可以重复,有序集合不能重复
- 列表是只有
element
,有序集合是element+score
重要API
基本操作
zadd key score element
:添加score和element—时间复杂度O(logn)zrem key element
:删除多个元素zscore key element
:获取一个元素的分数zincrby key increScore element
:给element增加指定的increScorezcard key
:返回元素的个数zrange key start end [withscores]
:返回指定索引范围内升序的数据,withscores是否打印分数zrangebyscore key minscore maxscore [withscores]
:返回指定分数范围内升序的数据,withscores是否打印分数zcount key minscore maxscore [withscores]
:返回指定分数范围内数据的个数,withscores是否打印分数zremrangebyrank key start end [withscores]
:zremrangebyscore key minscore maxscore [withscores]
:删除指定分数范围内的升序数据
实战
需求
- 排行榜
需求
- 如果没有数据,使用
zadd
进行分数的添加 - 如果有数据,使用
zincrby key increScore element
进行数据的增加 zrange
或者zrangebyscore
,进行获取数据