Redis基础你掌握多少了?来查漏补缺?

Redis 是什么

Redis开源内存 中的数据结构存储系统,它能够用做数据库缓存消息中间件。它支持多种类型的数据结构,如 字符串strings散列 hashes列表 lists集合 sets有序集合 sorted sets 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。redis

Redis 还内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不一样级别的 磁盘持久化(persistence), 并经过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。数据库

嗯,没错这就是 redis 中文官方网站上面的介绍,简洁明了。编程

NoSQL 是什么

咱们知道 redis 是一种非关系型数据库 NoSQL 。而为何出现 NoSQLNoSQL 又是什么呢?数组

单机数据库的年代

在一个网站访问量不大的时候,咱们使用一个数据库就足以应对流量请求。 缓存

缓存 + 拆分

随着访问量的上升,一个数据库已经不能知足咱们的需求了。为了更高的性能,咱们在中间加上了一个缓存层而且将数据库作了集群、结构优化和读写分离。服务器

而这里的缓存就是 NoSQL,固然作缓存也只是 NoSQL 的一种功能,就像 Redis 并不只仅有缓存这一种功能。好比它还能实现 简单的消息队列解决Session共享计数器排行榜好友关系处理 等等功能,可见 Redis 是一个很是强大工具,让咱们来学习它吧!网络

Redis 通用命令

首先咱们抛开数据类型来说关于 Redis 的通用命令。数据结构

操做 key 和 value

Redis 是一种 key value 存储的缓存数据库,全部的数据都有一个本身惟一的key。app

这里为了方便演示,我使用了字符串相关的设置命令 编程语言

  • keys [pattern] 获取符合要求的全部key。时间复杂度为 O(n),通常在生产环境中不使用,由于 Redis单线程的,执行耗时的任务会阻塞其余任务。通常会使用 scan 命令替代(非阻塞)。

  • dbsize 获取当前存储数据个数。
  • exists key 判断是否存在该key
  • del key 删除指定数据
  • type key 获取指定key的数据类型
  • rename key newkey 重命名

过时时间

Redis 中不少数据都是用来做为缓存数据的,而做为缓存就须要有过时时间,在 Redis 中提供了很强大的过时时间设置功能。

  • expire key seconds 为某个 key 设置过时时间。
  • ttl key 查看某个 key 的剩余时间,返回正数表明剩余的时间,-1表明永久,-2表明已过时或不存在。

Redis 的五种基本数据类型

在上面我说到了不少 Redis 做为缓存能实现的其余功能,好比计数器,排行榜,好友关系等,这些实现的依据就是靠着 Redis 的数据结构。在整个 Redis 中一共有五种基本的数据结构(还有些高级数据结构之后会讲),他们分别是 字符串strings散列 hashes列表 lists集合 sets有序集合 sorted sets

字符串 string

在绝大部分编程语言中都有 String 字符串类型,对于做为数据库的 Redis 也是必不可少的。

  • set key value 设置值
  • get key 获取某个key的值
  • mset key1 value1 key2 value2 批量设置而且是原子的,能够用来减小网络时间消耗
  • mget key1 key2 批量获取而且是原子的,能够用来减小网络时间消耗
  • incr key 自增指定key的值
  • decr key 自减指定key的值
  • incrby key value 自增指定数值
  • decrby key value 自减指定数值
  • incrbyfloat key floatvalue 增长指定浮点数 前面几个操做就能够用来实现计数器的功能。
  • setnx key value 若是不存在该key则能够设置成功,不然会失败,加上过时时间限制,则是redis实现分布式锁的一种方式(后面会提到)
  • set key value xx 与前面相反,若是存在则设置成功,不然失败(至关于更新操做)
  • getset key newvalue 设置新值并返回旧值
  • append key value 为本来内容追加内容
  • strlen key 获取字符串长度
  • getrange key start end 获取指定范围的内容
  • setrange key index value 设置指定范围的内容
  • setex key seconds value 设置值且设置过时时间
  • set key value ex seconds nx 为不存在的key设置值且设置过时时间,分布式锁的实现方式

hash

其实咱们能够理解 hash小型RedisRedis 在底层实现上和 Java 中的 HashMap 差很少,都是使用 数组 + 链表 的二维结构实现的。

不一样的是,在 Redis 中字典的值只能是字符串,并且他们 rehash 的方式不同,在 Redis 中使用的是 渐进式rehash

在 rehash 的时候会保留新旧两个 hash 字典,在数据迁移的时候会将旧字典中的内容一点一点迁移到新字典中,查询的同时会查询两个 hash 字典,等数据所有迁移完成才会将新字典代替就字典。

下面咱们来看一下关于 hash 的基本操做。

  • hset key field value 设置字典中某个key的值
  • hsetnx key field value 设置字典中某个key的值(不存在的)
  • hmset key field1 value1 field2 value2 ... 批量设置
  • hget key field 获取字典中某个key的值
  • hmget key field1 field2 批量获取
  • hgetall key 获取所有
  • hdel key field 删除某个key
  • hexists key field 判断是否存在
  • hlen key 获取指定key对应的字典中的存储个数
  • hvals key 返回全部的value
  • hkeys key 返回全部的key
  • hincrby key field increValue 增长某个value的值(也能够增长负数)
  • hincrbyfloat key field floatValue 增长某个value的值(浮点数)

list

Redis 中的列表至关于 Java 中的 LinkedList(双向链表) ,也就是底层是经过 链表 来实现的,因此对于 list 来讲 插入删除操做很快,但 索引定位很是慢

Redis 提供了许多对于 list 的操做,如等操做,你能够充分利用它们来实现一个 或者 队列

下面咱们来看一下关于 list 的基本操做。

  • lpush key item1 item2 item3... 从左入栈
  • rpush key item1 item2 item3... 从右入栈
  • lpop key 从左出栈
  • rpop key 从右出栈
  • lindex key index 获取指定索引的元素 O(n)谨慎使用
  • lrange key start end 获取指定范围的元素 O(n)谨慎使用
  • linsert key before|after item newitem 在指定元素的前面或者后面添加新元素
  • lrem key count value 删除指定个数值为value的元素
    • count = 0 :删除全部值为value的元素
    • count > 0 :从左到右删除 count 个值为 value 的元素
    • count < 0 :从右到作删除 |count| 个值为 value 的元素
  • ltrim key start end 保留指定范围的元素
  • lset key index newValue 更新某个索引的值
  • blpop key timeout 没有则阻塞(timeout指定阻塞时间 为0表明永久)
  • brpop key timeout 没有则阻塞(timeout指定阻塞时间 为0表明永久) 这两个能够用来实现消费者生产者

总结来讲咱们可使用 左入又出或者右入左出 来实现队列,左入左出或者右入右出 来实现栈

  • lpush + lpop = Stack
  • rpush + rpop = Stack**
  • lpush + rpop = Queue
  • rpush + lpop = Queue
  • lpush/rpush + ltrim = Capped List (定长列表)
  • lpush + brpop = Message Queue (消息队列)
  • rpush + blpop = Message Queue (消息队列)

set

Redis 中的 set 至关于 Java 中的 HashSet(无序集合),其中里面的元素不能够重复,咱们能够利用它实现一些去重的功能。咱们还有对几个集合进行取交集取并集等操做,这些操做就能够获取不一样用户之间的共同好友,共同爱好等等。

下面咱们就来看一下关于 set 的一些基本操做。

  • sadd key value 添加元素
  • sdel key value 删除某个元素
  • sismember key value 判断是不是集合中的元素
  • srandmember key count 随机获取指定个数的元素(不会影响集合结构)
  • spop key count 从集合中随机弹出元素(会破坏结合结构)
  • smembers key 获取集合全部元素 O(n)复杂度
  • scard key 获取集合个数
  • sinter set1 set2 ... 获取全部集合中的交集
  • sdiff set1 set2 ... 获取全部集合中的差集
  • sunion set1 set2 ... 获取全部集合中的并集

zset

Redis 中的 zset 是一个 有序集合,经过它能够实现不少有意思的功能,好比学生成绩排行榜,视频播放量排行榜等等。

zset 中是使用 跳表 来实现的,咱们知道只有数组这种连续的空间才能使用二分查找进行快速的定位,而链表是不能够的。跳表帮助链表查找的时候节省了不少时间(使用跳的方式来遍历索引来进行有序插入),若是不了解跳表的同窗能够补习一下。

下面咱们来看一下关于 zset 的一些基本操做。

  • zadd key score element 添加,score用于排序,value须要惟一,因为使用的跳表,时间复杂度为 O(logn)。
  • zrem key element 删除某元素 O(1)时间复杂度
  • zscore key element 获取某个元素的分数
  • zincrby key incrScore element 增长某个元素的分数
  • zrange key start end [withscores] 获取指定索引范围的元素 加上withscores则返回分数 O(logn + m)时间复杂度
  • zrangebyscore key minScore maxScore [withscores] 获取指定分数范围的元素 加上withscores则返回分数,O(logn + m)时间复杂度
  • zcard key 获取有序集合长度

Redis 中的事务和管道

管道 Pipeline

在某些场景下咱们在一次操做中可能须要执行多个命令,而若是咱们只是一个命令一个命令去执行则会浪费不少网络消耗时间,若是将命令一次性传输到 Redis 中去再执行,则会减小不少开销时间。 可是须要注意的是 pipeline 中的命令并非原子性执行的,也就是说管道中的命令到达 Redis 服务器的时候可能会被其余的命令穿插。

事务

关系型数据库具备 ACID 特性,Redis 能保证A(原子性)和I(隔离性),D(持久性)看是否有配置 RDB或者 AOF 持久化操做,但没法保证一致性,由于 Redis 事务不支持回滚

咱们能够简单理解为 Redis 中的事务只是比 Pipeline 多了个原子性操做,也就是不会被其余命令给分割,如上图。

  • multi 事务开始的标志

  • exec 事务执行

  • discard 清除在这个事务中放入队列的全部命令,即解除整个事务。

  • watch key 在事务开始前监控某个元素,若是在提交事务的时候发现这个元素的值被其余客户端更改了则事务会运行失败。

  • unwatch key 解除监控

Redis经常使用命令总结

好了,这就是这篇文章所有的内容了,对于 Redis 你还有多少遗忘的或者没学习到的呢?

若是文章对你有帮助的话,请给我点个赞哦(#^.^#)

关于 Redis 的文章接下来还会再写,若是感兴趣能够关注我(#^.^#)。

相关文章
相关标签/搜索