1. 缓存Cache
1.1. 缓存的概念
1.2. 缓存击穿
缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,该key没有命中,大量请求穿透到数据库服务器.
解决办法:对于热点数据,慎重考虑过期时间,确保热点期间key不会过期,甚至有些可以设置永不过期
1.3. 缓存雪崩
大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。
解决办法:不同的key,设置不同的过期时间(随机值),让缓存失效的时间点尽量均匀;使用高可用的分布式缓存集群,确保缓存的高可用性,做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2。
1.4. 缓存穿透
访问缓存中一个一定不存在的key,缓存不起作用,请求会穿透到DB,流量大时DB会挂掉,该key没有命中,去后端DB获取;
解决办法:布隆过滤器,访问key未在DB查询到值,也将空值写进缓存,但可以设置较短过期时间
1.5. 缓存一致性
当数据的时效性要求很高的时候,要保证缓存中的数据与数据库中的保持一致,需要保证缓存节点和副本中额数据也保持一致,不能出现差异现象。
对同一个数据进行读写,在数据库层面并发的读写并不能保证完成顺序;
发生了写请求A,A的第一步淘汰了cache;A的第二步写数据库,发出修改请求;
发生了读请求B,B的第一步读取cache,发现cache中是空的;B的第二步读取数据库,发出读取请求,
如果A的第二步写数据还没完成,读出了一个脏数据放入cache;
解决办法:一般会在数据发生更改的时,主动更新缓存中的数据或者移除对应的缓存。
2. Redis
2.1. 简介
开源,基于内存存储,可以用作数据库、缓存和消息中间件。
它支持多种类型的数据结构,Redis 内置了复制(replication),LUA脚本(Lua scripting),LRU
驱动事件(LRU eviction),事务(transactions)和不同级别的 磁盘持久化(persistence), 并通
过Redis哨兵(Sentinel) 和自动分区(Cluster)提供高可用性(high availability)
2.2. Redis性能
测试完成了50个并发执行100000个请求。设置和获取的值是一个256字节字符串。
结果:读的速度是110000次/s,写的速度是81000次/s
总结:非常快
2.3. 支持语言
3. Redis的操作
3.1. 操作Key
exist查询key是否存在
keys查询是否存在指定的key
type 查询key的数据类型
scan 扫描当前库中所有的key
3.2. 操作String
set :添加一条String类型数据
get :获取一条String类型数据
mset :添加多条String类型数据
mget :获取多条String类型数据
incr :增加1
decr:减少1
3.3. 操作hash
hset :添加一条hash类型数据
hget :获取一条hash类型数据
hmset :添加多条hash类型数据
hmget :获取多条hash类型数据
hgetAll :获取指定所有hash类型数据
hdel :删除指定hash类型数据(一条或多条)
3.4. 操作list
lpush :左添加(头)list类型数据
rpush :右添加(尾)类型数据
lrange : 获取list类型数据start起始下标 end结束下标 包含关系
llen :获取条数
lrem :删除列表中几个指定list类型数据
lrem key count value
count > 0 从前向后删除count个value
count <0 从后向前删除 绝对值(count) 个value
count = 0 删除所有的value
3.5. 操作set
sadd :添加set类型数据
smembers :获取set类型数据
scard :获取条数
srem :删除数据
3.6. 操作sorted set
sorted set是通过分数值来进行排序的,分数值越大,越靠后。
zadd :添加sorted set类型数据
zrange :获取sorted set类型数据
zcard :获取条数
zrem :删除数据
zadd需要将Float或者Double类型分数值参数,放置在值参数之前
zscore
3.7. 操作namespace
3.8. 操作失效时间
Redis 有四个不同的命令可以用于设置键的生存时间(键可以在多久)或过期时间(键什么时候会被删除) :
EXPlRE <key> <ttl> :用于将键 key 的生存时间设置为 ttl 秒。
PEXPIRE :用于将键 key 的生存时间设置为 ttl` 毫秒。
EXPIREAT <key> < timestamp> :用于将键 key 的过期时间设置为 timestamp 所指定的秒数时间戳。
PEXPIREAT <key> < timestamp > :用于将键 key 的过期时间设置为 timestamp 所指定的毫秒数时间
戳。
TTL :获取的值为-1说明此 key 没有设置有效期,当值为-2时证明过了有效期。
3.9. 删除
del :用于删除数据(通用,适用于所有数据类型)
hdel :用于删除hash类型数据
4. Redis的事务机制
Redis事务是一个耽误的隔离操作,事务中的所有命令都会序列化,按顺序的进行。事务在执行的过程中不会被其他客户端发来的命令请求打断。
Redis事务的主要作用就是串联多个命令防止别的命令插队
4.1. Multi(开启事务)、Exec(执行事务)、discard(放弃事务组队)
输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,
输入Exec后,Redis会将之前的命令队列中的命令依次执行。
组队的过程中可以通过discard来放弃组队、
4.2. 事务的错误处理
组队阶段某个命令出现了报告错误,执行时整个的所有队列会都会被取消。
执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会
回滚。
4.3. 事务锁的机制
4.3.1. 悲观锁
悲观锁假设并发冲突一定会发生,因此在操作数据前会主动加锁,阻止其他线程 / 进程同时修改数据,直到当前操作完成并释放锁。核心是 “先锁后操作”,牺牲并发效率换取数据一致性。
4.3.2. 乐观锁
乐观锁假设并发冲突不会发生,因此操作数据前不主动加锁,而是在 “提交修改” 时通过版本校验或CAS(Compare And Swap) 机制检测数据是否被其他线程修改:若未修改,执行更新;若已修改,放弃操作或重试。核心是 “先操作后校验”,牺牲部分一致性换取高并发效率。
5. 数据的持久化
redis是一个内存数据库,数据保存在内存中,虽然内存的数据读取速度快,但是很容易发生丢失。
5.1. RDB(Redis DataBase)默认方式全量
RDB--Fsimage(Redis DataBase)间隔生成数据集的时间点快照文件名为dump.rdb有可能丢失数据,但是恢复快有三种触发方式:save bgsave自动化
save:立马停止RedisServer对外的服务,开始将内存中的数据保存到硬盘指定的位置默认保存在:命令执行所在的文件目录
bgsave:Redis主进程创建一个子进程,子进程主要负责将内存中的数据持久化到硬盘,当子进程结束后告诉主进程成功
自动化:Redis根据配置文件每过一定的间隔保存一个一次rdb文件save <seconds><changes>
save 9001只要900秒内操作1次就进行保存
save 300 10 只要300秒内操作10次就进行保存
save 6010000只要60秒内操作10000次就进行保存
5.1.1. RDB的优势和劣势
- 优势
-
- RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。
- 生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作
- RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
- 劣势
-
- 当进行快照持久化时,会开启一个子进程专门负责快照持久化,子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。
5.2. AOF(Append Only File)增量
AOF 的核心思想是 “记录操作而非记录数据”:
全量备份总是耗时的,有时候我们提供一种更加高效的方式AOF,工作机制很简单,Redis会将每
一个收到的写命令都通过write函数追加到文件中。通俗的理解就是日志记录。
AOF--Edits(Append Only File)Redis会将每一个收到的写命令都通过write函数追加到文件中随着时间的增长,日志的量越来越大,重启Redis时间不可控
AOF的时机
728 appendfsync always 时时刻刻
729 appendfsync everysec每秒钟
730 appendfsync no 不写
Rewrite将内存中的数据用命令重写一遍,减少日志
Rewrite时机
770 auto-aof-rewrite-percentage 100771 auto-aof-rewrite-min-size 64mb
- 命令追加(Append)
Redis 执行完一个写命令后,会先将命令追加到内存中的 AOF 缓冲区(避免频繁直接写磁盘,提升性能)。 - 文件写入(Write)
缓冲区中的命令会被定期写入到 AOF 文件(操作系统层面的 “写入”,此时数据可能还在 OS 缓存中,未真正落盘)。 - 文件同步(Sync)
通过调用操作系统的fsync
或fdatasync
函数,将 OS 缓存中的数据强制刷写到磁盘(确保断电后数据不丢失)。
- 自动触发:通过配置
auto-aof-rewrite-percentage
(默认 100%)和auto-aof-rewrite-min-size
(默认 64mb),当 AOF 文件大小超过 “上一次重写后的大小 × 百分比” 且达到最小 size 时,自动触发重写。 - 手动触发:执行
BGREWRITEAOF
命令,Redis 会在后台异步完成重写(不阻塞主线程)。
6. 主从复制集群
Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。
6.1. 数据同步机制
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。
6.1.1. 全量同步
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一
份从服务器连接主服务器,发送SYNC命令;
主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执
行的所有写命令;
主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的
写命令;
从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
6.1.2. 增量同步
Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过
程。
增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务
器接收并执行收到的写命令。
主从复制的异步特性
主从复制对于主redis服务器来说是非阻塞的
这意味着当从服务器在进行主从复制同步过程中,主redis仍然可以处理外界的访问请求;
主从复制对于从redis服务器来说也是非阻塞的
这意味着,即使从redis在进行主从复制过程中也可以接受外界的查询请求,只不过这时候从redis返回的是以前老的数据