概述

Redis(Remote Dictionary Server ),即远程字典服务,是⼀个开源的使⽤ ANSI C 语⾔编写、⽀持⽹络、可基于 内存亦可持久化的⽇志型、Key-Value数据库,并提供多种语⾔的 API。

redis ⾃身是⼀个 Map ,其中所有的数据都是采⽤ 有具体类型的数据。 key : value 的形式存储 key 是⼀个字符串, value 是具 Redis 中包含5种基本数据类型和3种特殊类型。

命令

基本命令

#1.切换数据库
select index
​
#2.清屏命令
clear
​
# 3.获得当前库中的key
# "*"匹配任意数量的任意字符 "?"匹配任意⼀个字符 "[]"匹配其中的任意⼀个字符
keys pattern
keys * (获得所有的key)
keys d* (获得所有以d开头的key)
keys *blue (获得所有以blue结尾的key)
keys ?ava (获得前⾯有⼀个任意字符,并且以ava结尾的key)
keys u[se]r (获得前⾯第⼀个字符是u,第⼆个字符是s或e,结尾为r的key)
​
# 4.判断key是否存在
exists key
​
# 5.判断key是什么类型
type key
​
# 6.删除指定的key
del key
​
# 7.设置key的过期时间
expire key 1 (秒为单位)
pexpire key 1 (毫秒为单位)
​
# 8.查看过期剩余时间(-1表示永不过期,-2表示已过期)
ttl key
​
# 9.将key的有效期设置为永不过期
persist key
​
# 10.修改key的名字
rename key newkey #如果newkey存在则会替换原来的value
rename str str1 #将str的key改名为str1
renamenx str str1 #将str的key改名为str1,如果str1不存在才修改,如果存在则修改失败
​
# 11.对key中的数据进⾏排序,只针对集合类型(list,set)
sort key
sort list [asc|desc] #对key为list的集合进⾏排序(注意不改变原始数据)
​
# 12.查看库中key的数量
dbsize
​
# 13.清楚当前库的所有key
flushdb
​
#14.清除所有库中的数据(经常用)
flushall
​
# 15.退出命令
quit exit ESC键
​
# 16.检测客户端与服务器连通命令
ping
​
# 17.控制台打印命令
echo message
​
# 18.数据在不同的库中移动  move key db
move name 1 #将当前库中的name数据移动到1号库中(注意:当前库中存在name数据,1号库中不存在同名的数据)
​
# 19.获得当前Redis的运⾏属性值
info

字符串相关命令(重)

String 是 Redis 中最基本的类型, String 类型是⼆进制安全的,redis 的 string 可以存储任何数据,如图 片、对象等。

# 存值命令
set key value # 存放单个元素
mset key1 value1 key2 value2 key3 value3 ... # 批量存放
​
# 取值命令 获取数据时返回值为nil表示空,没有获取数据
get key # 获取单个元素
mget key1 key2 key3 ... # 批量获取多个元素
​
# 获得字符串的⻓度
strlen key
​
# 向value中追加数据(如果原始数据存在就追加,否则新建)
append key value
​
# 截取字符串 endIndex:-1代表⾃然结束
getrange key startIndex endIndex
​
# 替换内容
setrange key startIndex 替换内容
​
# 如果存在就不设置,不存在就新建
setnx key value #如果存在什么都不做,如果不存在就新建⼀个数据
​
# 数值运算指令
# 加法操作
incr key #对key的值⾃加1,等同于i++
incrby key number #对key的值加上指定的数值(负值进⾏减法运算),等同于i=i+n
​
# 减法运算
decr key #对key的值⾃减1,等同于i--
decr by key number #对可以的值减去指定的数值
​
# 设置带有时效的数据
# 以秒为单位设置存活时间
setex key seconds value
​
# 以毫秒为单位设置存活时间
psetex key milliseconds value
​
# 使⽤set⽅式设置key的存活期
set key value [ex seconds][px milliseconds]

Hash 相关命令(重)

# 添加/修改数据
hset key field value
​
# 获取数据
hget key field
​
# 删除数据
hdel key field
​
# 添加/修改多个数据
hmset key field1 value1 field2 value2 ...
​
# 获取多个数据
hmget key field1 field2 ...
​
# 获取hash中的字段数量
hlen key
​
# 获取hash中是否包含指定字段
hexists key field
​
# 获取hash中的所有字段名和字段值
hkeys key #获得所有的字段名
hvals key #获得所有字段值
​
# 设置指定字段的数值增加或减少
hincrby key field number #增加或减少整数(负数为减少)
hincrbyfloat key field number #增加或减少⼩数(负数为减少)

List 相关命令(重)

# 向列表中添加数据(左部添加/右部添加)
lpush key value #向队列的头部插⼊元素(左)
lpush list aaa #向队列的头部插⼊⼀个元素
lpush list aaa bbb ccc #向队列中插⼊多个元素
rpush key value #向队列的尾部插⼊元素(右)
rpush list aaa #向队列的尾部插⼊⼀个元素
rpush list aaa bbb ccc #向队列中插⼊多个元素
​
# 从list中获取元素
lrange key startIndex endIndex #根据起始和结束下标获取此范围内的列表元素
lrange list 0 1 #结果 aaa,bbb
lrange list 0 -1 #将list中的所有元素取出
​
# 从list中弹出元素
lpop key #获得列表头部的第⼀个元素并从列表中移除
lpush list aaa bbb ccc ddd
lpop key #获取并移除元素"ddd"
rpop key #获得列表尾部的第⼀个元素并从列表中移除
rpop key #获取并移除元素aaa
​
# 通过下标获取list中的某个元素
lindex key index
​
# 获得列表中元素的数量(⻓度)
llen key
​
# 根据元素值从列表中移除指定数量的元素
lrem key count value
lrem list 2 aaa #将list中的aaa元素移除,存在两个移除两个(最多移除两个)
​
# 截取⼦list(截断⼦元素)
ltrim key start end
lpush list aaa bbb ccc ddd eee
ltrim list 0 3 结果:eee ddd ccc bbb
​
# 将原列表中最后⼀个元素移到新列表中
rpoplpush oldkey newkey
lpush list aaa bbb ccc ddd eee
rpoplpush list newlist #将list中的最后⼀个元素移动到newlist中
lrange list #结果 bbb ccc ddd eee
lrange newlist #结果 aaa
​
# 根据下标重置list中的⼀个元素(根据下标修改list中的⼀个元素)
lset key index value
​
# 向某个元素前或后插⼊⼀个元素
linsert list before|after oldvalue insertvalue

Set 相关命令

# 向set集合添加⼀个元素
sadd key value1 value2 ....
​
# 查看set集合中的所有元素
smembers key
​
# 判断⼀个元素是否存在于set集合中(0表示不存在 1表示存在)
sismember key value
​
# 获取set中元素的个数
scard key
​
# 移除⼀个元素
srem key value
​
# 随机抽取⼀个元素
srandmember key [count] #随机抽取⼀个或多个元素
​
# 随机删除元素
spop key [count] #随机删除⼀个或多个元素
​
# 将⼀个特定的值,移动到另⼀个set集合中
smove oldkey newkey value
​
# 集合操作
# 1. 差集
sdiff key1 key2
# 2. 交集
sinter key1 key2
# 3. 并集
sunion key1 key2

ZSet 相关命令

该集合是对 set 集合的改造,在 set 集合中加⼊了⼀个字段值,⽤于存储排序规则数据,该数据只负责排序不起 其他作⽤。

# 向zset集合添加元素
zadd key score1 value1 score2 value2 #向zset集合添加⼀个或多个成员
​
# 获取zset中的元素
# 1.zrange key start end [withscores] #从⼩到⼤的顺序显示元素信息,withscores显示排序规则字段
# 2.zrevrange key start end [withscores] #从⼤到⼩的顺序显示元素信息,withscores显示排序规则字段
# 按条件获取zset中的元素
# 1.zrangebyscore key min max [limit] [withscores]
zrangebyscore salary 9000 12000 limit 0 2 withscores #查询⼯资在9000到12000之间的员⼯名并显示前
两个
# 2.zrevrangebyscore key max min [limit] [withscores] #降序
zrevrangebyscore salary 13000 10000 limit 0 2 withscores #查询⼯资在12000到90000之间的员⼯名并
显示前两个
​
# 增加或减少zset中元素的score值
zincrby key increment value
zincrby topn 200 java #把key为topn的的java属性的score添加200
​
# 删除zset中的元素
zrem key member1 member2 ... #根据元素名删除⼀个或多个元素
zrem salary xiaoming xiaoqiang
zremrangebyrank key start stop #删除下标指定范围的元素
zremrangebyrank salary 0 2
zremrangebyscore salary min max #根据socres指定范围删除元素
zremrangebyscore salary 9000 12000
​
# 获取指定值的分数
zscore key value
​
# 获得元素在集合中的排名
zrank key member # 升序排名
zrank topn java #排名从0开始,根据score升序排序
zrevrank key member # 降序排名
zrevrank topn java #排名从0开始,根据score降序排序
​
# 获得集合中元素数量
# 1.zcard key #获得集合中元素数量
zcard salary
# 2.zcount key min max #获得指定范围的元素数量
zcount salary 9000 12000
​
# 集合交集和并集
#1.zinterstore newset setcount set1 set2 ...#集合交集操作,将多个集合的交集存⼊到newset集合中,相
交集合的数量个setcount指定的数量要⼀致,默认对交集数据进⾏求和运算,也可以获得最⼤值或最⼩值等运算
zinterstore ss 2 s1 s2 [aggregate max|min]
#2.zunionstore newset setcount set1 set2 ...#集合并集操作
zunionstore ss 2 s1 s2 [aggregate max|min]

使用redis的原因

随着移动互联⽹的快速发展,互联⽹的⽤户数量越来越多,产⽣的数据规模也越来越⼤,对数据库也提出了更⾼的 要求,为了减少直接访问数据库,我们会⽤ Redis 作为缓存层。 因为 Redis 是内存数据库,我们可以将数据库的数据缓存在 Redis ⾥,相当于数据缓存在内存,内存的读写速 度⽐硬盘快好⼏个数量级,这样⼤⼤提⾼了系统性能。

雪崩、击穿、穿透的理解

缓存雪崩

通常我们为了保证缓存中的数据与数据库中的数据⼀致性,会给 Redis ⾥的数据设置过期时间,当缓存数据过期 后,⽤户访问的数据如果不在缓存⾥,业务系统需要重新⽣成缓存,因此就会访问数据库,并将数据更新到 Redis ⾥,这样后续请求都可以直接命中缓存。

当大量数据在同一时间过期时或者 Redis 故障宕机时,这时⼤量的⽤户请求,因为redis中数据过期了,所以就直接访问到数 据库了,从⽽导致数据库的压⼒骤增,严重的会造成数据库宕机,从⽽造成整个系统崩溃,这就是造成缓存雪崩的 原因。

雪崩的主要原因:

1.⼤量数据同时过期。

2.Redis 故障宕机。

解决方法:
针对大量数据过期的解决办法:

1.均匀设置过期时间

如果要给缓存数据设置过期时间,应该避免将⼤量的数据设置成同⼀个过期时间。我们可以在对缓存数据设置过期 时间时,给这些数据的过期时间加上⼀个随机数,这样就保证数据不会在同⼀时间过期。

2.互斥锁

当业务线程在处理⽤户请求时,如果发现访问的数据不在 Redis ⾥,就加个互斥锁,保证同⼀时间内只有⼀个请 求来构建缓存,当缓存构建完成后,再释放锁。未能获取互斥锁的请求,要么等待锁释放后重新读取缓存,要么就 返回空值或者默认值。

3.双 key 策略

我们对缓存数据可以使⽤两个 key ,⼀个是主 key 不⼀样,但是 key ,会设置过期时间,⼀个是备 key ,不会设置过期,它们只是 value 值是⼀样的,相当于给缓存数据做了个副本。

4.后台更新缓存

业务线程不再负责更新缓存,缓存也不设置有效期,⽽是让缓存“永久有效”,并将更新缓存的⼯作交给后台线程定 时更新。

Redis 故障宕机解决办法:

1.服务熔断或请求限流机制

因为 Redis 故障宕机⽽导致缓存雪崩问题时,我们可以启动服务熔断机制,暂停业务应⽤对缓存服务的访问,直接 返回错误,不⽤再继续访问数据库,从⽽降低对数据库的访问压⼒,保证数据库系统的正常运⾏,然后等到 Redis 恢复正常后,再允许业务访问缓存服务。

服务熔断机制是保护数据库的正常允许,但是暂停了业务应⽤访问缓存系统,全部业务都⽆法正常⼯作。

2.构建 Redis 缓存⾼可靠集群

服务熔断或请求限流机制是缓存雪崩发⽣后的应对⽅案,我们最好通过主从节点的⽅式构建 集群。 Redis 缓存⾼可靠集群。如果 Redis 缓存的主节点故障宕机,从节点可以切换成主节点,继续提供缓存服务,避免了由于 Redis 故障宕 机⽽导致缓存雪崩问题。

缓存击穿

我们的业务通常会有⼏个数据会被频繁地访问,⽐如秒杀活动,这类被频繁地访问的数据被称为热点数据。 如果缓存中的某个热点数据过期了,此次⼤量的请求访问了该热点数据,就⽆法从缓存中读取,直接访问数据库, 数据库很容易就被⾼并发的请求冲垮,这就是缓存击穿的问题。

原因流程:

1.大量的读请求

2.请求中的部分热点数据过期,导致缓存失败

3.因为访问redis没有得到数据,所以转为大量的请求去直接访问数据库

通俗例子:

双⼗⼀小马突发奇想,想拍卖一双有科比签名的篮球鞋,程序员将该鞋的信息存到了 redis 中,设置了3⼩时过期。寻思3⼩时够他们抢了吧,但他低估了科比的魅⼒。 该商品引起了⼀千万⼈关注,这些⼈不断的竞拍这双鞋,价格越拍越⾼,小马乐开了花。 竞拍了2⼩时59分,⻢上要拍到⼀个亿了,突然这双鞋在 redis ⾥的 key 数据过期了,导致该 key 的⼤量请 求,都打到了数据库,直接导致数据库挂掉了,服务⽆法响应。

意思就是非常多的请求正在访问一个数据,然后这个数据突然过期,那么直接全部去访问数据库,然后导致击穿。

解决办法:
1.互斥锁⽅案

保证同⼀时间只有⼀个业务线程更新缓存,未能获取互斥锁的请求,要么等待锁释放后重新读取 缓存,要么就返回空值或者默认值。

2.不给热点数据设置过期时间

由后台异步更新缓存,或者在热点数据准备要过期前,提前通知后台线程更新缓 存以及重新设置过期时间。

缓存穿透

当发⽣缓存雪崩或击穿时,数据库中还是保存了应⽤要访问的数据,⼀旦缓存恢复相对应的数据,就可以减轻数据 库的压⼒,⽽缓存穿透就不⼀样了。

当⽤户访问的数据,既不在缓存中,也不在数据库中,导致请求访问缓存时,发现缓存缺失,再去访问数据库时, 发现数据库中也没有要访问的数据,⽆法构建缓存数据来服务后续的请求。那么当有⼤量这样的请求到来时,数据 库的压⼒骤增,这就是缓存穿透的问题。

原因流程:

大量的请求访问redis,然后这些请求redis中没有,然后去访问数据库,数据库也没有,无法备份到redis中,然后就一直访问数据库,导致穿透。

缓存穿透发⽣的情况

缓存穿透的发⽣⼀般有这两种情况:

1.业务误操作,缓存中的数据和数据库中的数据都被误删除了,所以导致缓存和数据库中都没有数据。

2.⿊客恶意攻击,故意⼤量访问某些读取不存在数据的业务。

解决方法:

1.⾮法请求的限制。

判断请求参数是否合理,请求参数是否含有⾮法值、请求字段是否存在,如果判断出是恶意请求就直接返回错误,避免进⼀步访问缓存 和数据库。

2.缓存空值或者默认值。

当我们线上业务发现缓存穿透的现象时,可以针对查询的数据,在缓存中设置⼀个空值或者默认值,这样后续请求 就可以从缓存中读取到空值或者默认值,返回给应⽤,⽽不会继续查询数据库。

3.使⽤布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在。

使⽤布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在。我们可以在写⼊数据库数据 时,使⽤布隆过滤器做个标记,然后在⽤户请求到来时,业务线程确认缓存失效后,可以通过查询布隆过滤器快速 判断数据是否存在,如果不存在,就不⽤通过查询数据库来判断数据是否存在。

即使发⽣了缓存穿透,⼤量请求只会查询 Redis 和布隆过滤器,⽽不会查询数据库,保证了数据库能正常运⾏, Redis ⾃身也是⽀持布隆过滤器的。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐