通用命令

  • keys [parten] :获得数据库中所有的键--------(O(n),一般不会用)
  • dbsize:算出key的总数
  • exists key:判断key是否存在,存在返回1
  • del [key ... ]:删除多个key
  • expire 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种数据类型,包括StringListSetZsetHash,满足大部分的使用要求。每个数据结构由多种内部编码。

采用这种形式的原因是内存的空间比较珍贵,采用不同的编码主要应用于不同场景—时间换空间或者空间换时间

数据类型 可以存储的值 操作
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)=1
  • decr key:自减1,不存在 get(key)=-1
  • incrby key k :key 自增 k ,key不存在,自增后 get(k)=k
  • decrby key k:key自减 k,key不存在 ,自减后 get(key)=-k
  • mset 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对应filed
  • hexists 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增加指定的increScore
  • zcard 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,进行获取数据