[准备面试|Redis]- 基础知识

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

前言

本系列主要从基础知识,而后进阶,再逐步深入 Redis 的原理分析,以保证对 Redis 的学习深入浅出,学以致远并输出自己对 Redis 学习和了解的成果。本系列将划分四个部分:

基础知识

redis 是一个高性能、基于 Key-Value 的缓存与存储系统,通过提供多种键值数据类型来适应不同场景下的缓存与存储需求。

redis 的特性:

  • 性能高、读写速率高
  • 多样的数据类型:字符串类型、散列类型、列表类型、集合类型、有序集合类型等
  • 原子性:所有操作都是原子性,无论单个操作还是多个操作(多个操作支持事务)都是原子性的
  • 其他特性:集群、支持 public/subscrible ,通知,key 过期等特性

存储结构

redis 是一个基于键值对存储系统,属于 NoSQL 数据库。

所以 Redis 是以字典结构存储数据。其他应用通过 TCP 协议从字典中读写内容。类似:dict["key"] = "value"。所以说 Redis 支持多种数据类型,主要说的是 value 可支持的类型有多种:

  • 字符串类型 string
  • 散列类型 hash
  • 列表类型 list
  • 集合类型 set
  • 有序集合类型 zset

以上五种是最基本的数据类型,其还支持BitMaps位图Hyperloglogs基数统计Geospatial 地理位置 这三种特殊的数据类型,可能平常很少使用。

基本类型

字符串类型 string

字符串类型是最基本的数据类型,它和你的开发语言中的字符串一样。value 可以是普通字符串,数字字符串,json 格式字符串等任何形式的字符串,只要是字符串都可以进行存储。

SET key value
GET key
复制代码

当为整数形式的字符串时,Redis 还支持使用命令 INCR/DECR,功能是将指定key的value数值进行+1/-1,并返回递增后的值。需要注意,当 key 不存在时则会先被初始化为 0,然后再执行递增操作。若非整数类型则将报错。

类似场景:计数器、文章访问量统计

INCR key // 递增
复制代码

当然还支持很多方法:append 追加,MSet 批量设置等等

列表类型 list

列白类型是存储一个有序的字符串列表,常用的操作就是向列表两端添加元素或者获取列表的某一个片段。

列表类型内部使用双向链表实现,所以可以向列表的两端添加元素

RPUSH/LPUSH KEY value[value..] // 从左边/右边向列表中PUSH值(一个或者多个)。
LRANGE key start end 获取list 起止元素(索引从左往右 递增)
复制代码

应用场景

  • 消息队列

散列类型 hash

Hash 类型的键值也是一种字典结构,其存储了字段和字段值的映射,但字段值只能是字符串,不支持其它的数据类型。Hash 类型适合存储对象。

使用

// 查询哈希表中是否存在某字段
HEXISTS key field
// 赋值
HSET KEY FIELD VALUE
HMSET KEY FIELD VALUE [FIELD VALUE] // 批量
// 获取 HGET 删除 HDEL 
// 其他语法
HSETNX KEY FIELD VALUE //字段不存在时才设置哈希字段的值
复制代码

应用场景

  • 直接存储一个对象,如用户信息,文章数据

集合类型 set

一个集合中每个元素都是不同的,且没有顺序。类似一个数组一样,但每个元素只能是字符串类型。和列表区别在于列表是有序的,每个元素不一定唯一。

set 是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

SADD key member1 [member2]  //向集合添加一个或多个成员
SMEMBERS key  // 返回集合中的所有成员
复制代码

应用场景

类似掘金文章的标签,可以使用集合类型存储

有序集合类型 zset

有序集合 和集合 set 是一样,是string类型元素的集合,且不允许重复。但有序集合为集合中每个元素都关联一个double 类型的分数 score,通过 score 以保证集合的有序。

ZADD KEY score1 member1 【score2 member2】  //向有序集合添加一个或多个成员,或者更新已经存在成员的分数
ZRANGE key start end // 通过索引区间返回有序集合成指定区间内的成员
复制代码

有序集合和列表有些相似:

  • 都是有序的
  • 都可以获取某一范围的元素。

但,也有不同的地方:

  • 列表是通过双向链表实现的,两端都可以进行读写操作。当数据量比较大时,读取中间部分数据就会变慢,适合实现新鲜事或日志,这样很少访问的元素
  • 有序集合时使用 hash 表 和跳表实现,所以读取中间数据丢失很快的
  • 有序集合比列表更耗费内存
  • 列表 list 无法简单调整某元素的位置,但有序集合可通过 score 调整顺序

其他类型

  • HyperLogLog 类型 时用来做基数统计的算法。

    应用场景:网页的访问量(UV),一个用户多次访问,也只能算作一个人。

  • GEO 类型 主要用于存储地理位置信息,并对存储的信息进行操作

    geoadd:添加地理位置的坐标。
    geopos:获取地理位置的坐标。
    geodist:计算两个位置之间的距离。
    复制代码
  • BitMaps 位图: 使用位存储,信息状态只有 0 和 1,Bitmap是一串连续的2进制数字(0或1),每一位所在的位置为偏移(offset),在bitmap上可执行AND,OR,XOR,NOT以及其它位操作。

  • 流类型 stream 。Redis 5.0 版本新增的类型。

    • 流类型是对列表 list 类型的补充,所以其有列表类型的一些性质。但流类型仅在末尾追加内容。列表是可以在首部和中间插入内容
    • 流类型另一个作用是可以作为消息队列使用

一道问答题

场景:实现一个访客列表,记录每个访客 IP 和 Agent等相关信息,并要求可以后续可以通过时间范围查询访客记录,如何设计使用缓存?

答:通过使用有序集合进行缓存,每次访客生成客户 Id 最为 key ,value 是访客的相关信息。有序集合每个 key 都有对应的 score ,将当前时间设置为score 。

这样每次查询时就可以使用 zrangebyscore 获取时间范围内的访客ID,再使用 HGetAll 获取对应的内容

参考资料:

猜你喜欢

转载自juejin.im/post/7131021462953328648