文章目录

  • 一、Redis是什么?
  • 二、Redis的五种数据结构
  • 1,String(字符串)
  • 2,Hash(哈希)
  • 3,List(列表)
  • 4,Set(集合)
  • 5,有序集合(zset)
  • 三、Redis基础命令汇总
  • 1,通用命令
  • 2,字符串命令
  • 3,整数的操作
  • 4,小数的操作
  • 5,批量操作
  • 四、什么是缓存击穿、缓存穿透、缓存雪崩
  • 1,缓存击穿
  • 2,缓存穿透
  • 3,缓存雪崩



一、Redis是什么?

Redis,英文全称是Remote Dictionary Server(远程字典服务),是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

与MySQL数据库不同的是,Redis的数据是存在内存中的。它的读写速度非常快,每秒可以处理超过10万次读写操作。因此redis被广泛应用于缓存,另外,Redis也经常用来做分布式锁。除此之外,Redis支持事务、持久化、LUA 脚本、LRU 驱动事件、多种集群方案。


二、Redis的五种数据结构

redis 删除指定用户 redis删除命令_后端

1,String(字符串)

  • 简介:String是Redis最基础的数据结构类型,它是二进制安全的,可以存储图片或者序列化的对象,值最大存储为512M
  • 简单使用举例: set key value、get key等
  • 应用场景:共享session、分布式锁,计数器、限流。
  • 内部编码有3种,int(8字节长整型)/embstr(小于等于39字节字符串)/raw(大于39个字节字符串)

2,Hash(哈希)

  • 简介:在Redis中,哈希类型是指v(值)本身又是一个键值对(k-v)结构
  • 简单使用举例:hset key field value 、hget key field
  • 内部编码:ziplist(压缩列表) 、hashtable(哈希表)
  • 应用场景:缓存用户信息等

3,List(列表)

  • 简介:列表(list)类型是用来存储多个有序的字符串,一个列表最多可以存储2^32-1个元素。
  • 简单实用举例:lpush key value [value …] 、lrange key start end
  • 内部编码:ziplist(压缩列表)、linkedlist(链表)
  • 应用场景:消息队列,文章列表,

4,Set(集合)

  • 简介:集合(set)类型也是用来保存多个的字符串元素,但是不允许重复元素
  • 简单使用举例:sadd key element [element …]、smembers key内部编码:intset(整数集合)、hashtable(哈希表)
  • 注意点:smembers和lrange、hgetall都属于比较重的命令,如果元素过多存在阻塞Redis的可能性,可以使用sscan来完成。
  • 应用场景:用户标签,生成随机数抽奖、社交需求。

5,有序集合(zset)

  • 简介:已排序的字符串集合,同时元素不能重复
  • 简单格式举例:zadd key score member [score member …],zrank key member
  • 底层内部编码:ziplist(压缩列表)、skiplist(跳跃表)
  • 应用场景:排行榜,社交需求(如用户点赞)

三、Redis基础命令汇总

1,通用命令

返回所有 key,可以使用通配符来查询。
   # 查看所有 key 
    keys *
    
   # 查看以 hel 开头的 key
	keys hel*
	
   # 查看 ph + 一个字符
	keys ph?
	
   #统计当前 db key 的总数
    select 1
	dbsize
	
   #查看某个 key 是否存在,存在则返回 1,不存在返回 0
    exists key
    
   #删除一个或多个 key
   # 删除 key
	del key1
   # 删除 key1、key2
	del key1 key2

2,字符串命令

字符串的增删改查操作是 get、set、del。其中 set 操作可以是增加数据,也可以是更新数据。

# 增加 hello 的值为 world
set hello world

# 获取 hello 的值
get hello

# 更新 hello 的值为 "new world"
set hello "new world"

# 删除 hello
del hello

3,整数的操作

对于字符串类型的数据,可以存储字符串也可以存储整数,对于整数,有一些额外的操作,比如自增1,自减1,自增n,自减n。

# 为 a 初始化设置值为 3
set a 3

# 进行自增 1 的操作
incr a

# 进行自减 1 的操作
decr a

# 对 a 进行自增 5
incrby a 5

# 对 a 进行自减 5
decrby a 5
注意:如果 incr 和 decr 的 key 之前在 Redis 中不存在,那么系统会默认先 set key 0,然后进行自增自减的操作

4,小数的操作

对应于整数,小数也可以进行自增的操作

#incrbyfloat 自增某个小数
incrbyfloat a 3.4

#incrbyfloat 自减某个小数
incrbyfloat a -3.4

5,批量操作

批量获取 key 列表的值,比如我们有 a,b,c 三个 key,我们想同时返回三个 key 的数据

mget a b c
# 以下是返回:
#1) "abcdef"
#2) "1"
#3) "world"

批量设置 key 列表的值,一个 key 后跟一个 value,比如我们设置三个 key,a、b、c 的 value 分别是 1,2,3

mset a "1" b "2" c "3"

四、什么是缓存击穿、缓存穿透、缓存雪崩

1,缓存击穿

缓存击穿: 指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。

缓存击穿看着有点像,其实它两区别是,缓存雪奔是指数据库压力过大甚至down机,缓存击穿只是大量并发请求到了DB数据库层面。可以认为击穿是缓存雪奔的一个子集吧。有些文章认为它俩区别,是区别在于击穿针对某一热点key缓存,雪奔则是很多key。

解决方案就有两种:

  • 使用互斥锁方案。缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(Redis的setnx)去操作,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存
  • “永不过期”,是指没有设置过期时间,但是热点数据快要过期时,异步线程去更新和设置过期时间。

2,缓存穿透

redis 删除指定用户 redis删除命令_数据库_02


缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。

缓存穿透一般都是这几种情况产生的:

  • 业务不合理的设计,比如大多数用户都没开守护,但是你的每个请求都去缓存,查询某个userid查询有没有守护
  • 业务/运维/开发失误的操作,比如缓存和数据库的数据都被误删除了
  • 非法请求,比如故意捏造大量非法请求,以读取不存在的业务数据

如何避免缓存穿透呢? 一般有三种方法

  • 如果是非法请求,我们在API入口,对参数进行校验,过滤非法值。
  • 如果查询数据库为空,我们可以给缓存设置个空值,或者默认值。但是如有有写请求进来的话,需要更新缓存哈,以保证缓存一致性,同时,最后给缓存设置适当的过期时间。(业务上比较常用,简单有效)
  • 使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查

3,缓存雪崩

缓存雪奔: 指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至down机。

  • 缓存雪奔一般是由于大量数据同时过期造成的,对于这个原因,可通过均匀设置过期时间解决,即让过期时间相对离散一点。如采用一个较大固定值+一个较小的随机值,5小时+0到1800秒
  • Redis 故障宕机也可能引起缓存雪奔。这就需要构造Redis高可用集群啦