Redis复习大纲

1.redis是什么

是什么——非关系型数据库,一般作为缓存;可以在无锁的情况下完成所有操作,省去了多线程切换带来的时间和性能上的开销,也避免了死锁问题。


为什么这么快——大部分操作在内存中完成、单线程模型避免了内存竞争、I/O多路复用机制处理大量的客户端Socket请求。


是单线程的吗——是网络I/O线程,get、set操作是一个线程完成的;但持久化(AOF的重写机制、RDB的bgsave)、集群同步等操作是别的线程来完成的。虽然redis一直是单线程模型,但在redis6.0之后也采用了多个IO线程来处理网络请求,这是因为随着网络硬件的性能提升,redis的性能瓶颈有时会出现在网络的IO处理上,所以为了提高网络请求处理的并行度,redis6.0对于网络请求采用了多线程处理,但是对于读写命令,redis仍然是单线程来处理的。


2.数据结构


2.1一览


最常用的:String、hash、list、Set、ZSet。
其他:BitMap(位图)、HyperLogLog(统计)、GEO(地理空间)

其中zset的底层用到了ziplist(压缩链表)和skiplist(跳表)实现。
使用条件: 当zset满足以下两个条件的时候,使用ziplist:
1.保存的元素少于128个
2.保存的所有元素大小都小于64字节
不满足这两个条件则使用skiplist。
这两个数值是可以通过redis.conf的zset-max-ziplist-entries 和 zset-max-ziplist-value选项 进行修改。


2.2详细


2.2.1String

命令:
set-设置、get-获取;mset、mget-批量
INCR、DECR、INCRBY、DECRBY——数值增减

场景:

分布式锁
setnx key value
set key value [EX seconds] [PX milliseconds] [NX|XX]

对实时性和准确性要求不高,对性能要求高的统计,比如点赞,用INCR


2.2.2hash

命令:
hash的数据结构类似java的map,key是string,value是map。


HSET key field value
HGET key filed
HMSET、HMGET——批量
hgetall key——遍历获得所有字段值
hdel——删除key

场景:

购物车:
String是用户id、field是商品编号、value是购买个数
然后商品+1用hincrby、全选用hgetall、


2.2.3list

命令:
LPUSH key value [value ...]
RPUSH key value [value ...]——从左右添加元素
LRANGE key start stop —— 查看列表

场景:

推送更新列表


2.2.4set

命令:
SADD key member [member...] —— 添加
SREM key member [member...] —— 删除
SMEMBERS key——获取集合所有元素
SISMEMBER key member——判断是否在集合中
SRANDMEMBER key [数字]——随机弹出一个元素,不删除
SPOP key [数字]——随机弹出并删除
集合运算(差集、交集、并集),暂时略

场景:

抽奖:用随机弹出
点赞:用随机加入
共同关注:集合运算交集


2.2.5zset

命令:
ZADD key score member [score member ....] —— 添加
ZREM key member [member] —— 删除
ZRANGEBYSCORE key min max —— 获取指定分数区间的所有元素
ZINCRBY key 数字 member —— 增加多少个

场景:

热搜:用zincrby实时更新热搜



3.分布式锁

3.1手写实现

需要注意几点问题:
● lua脚本原子指令增加key
● 加锁失败则循环重试
● 添加过期时间防止死锁
● 过期时间自动续期
● 使用UUID防止误删


3.2框架实现

使用Redisson


4.持久化

AOF:将所有的操作命令以文本的形式追加到文件中。写后日志,只记录执行成功的,优点是不用进行语法校验,不会阻塞当前的写操作。缺点是数据可能会丢失(刚写入数据就宕机),可能阻塞其他操作(AOF是在主线程执行),数据恢复的读取时间长。
RDB:将某一时刻的内存数据,以二进制的方式写入磁盘。提供了两个命令,save和bgsave,save会阻塞主线程,bgsave则是创建子进程,是默认配置。缺点是保存某一时刻的快照,在这期间的数据不会及时被记录。
混合模式:4.0推出,为了解决上述两个模式的缺点。



RDB做快照时数据能被修改吗?——可以,持久化时主线程的写入会对修改的数据创建副本,bgsave子进程会把这个副本也写入到文件中,在这个过程中依然可以修改数据。

5.内存淘汰

5.1删除策略


● 64位操作系统内存大小默认就是计算机的内存大小,一般设置为最大内存的四分之三。
定时删除
在定时的时候会有大量性能消耗。CPU不友好。
惰性删除
用到了才会判断是否过期,不用到就永远不删除。内存不友好。
定期删除
二者结合。每隔一段时间抽取一部分数据判断过期。


5.2缓存淘汰策略


8种策略
默认是:noeviction——内存满了也不驱逐,直接报OOM
还有7种:
allkeys-lru——对所有key使用lru算法进行删除;
volatile-lru——对所有设置了过期时间的key使用lru算法进行删除;
allkeys-lfu——对所有key使用lfu算法进行删除;
volatile-lfu——对所有设置了过期时间的key使用lfu算法进行删除;
allkeys-random——对所有key随机删除;
volatile-random——对所有设置了过期时间的key随机删除;
volatile-ttl——删除马上要过期的key;
其中lru:最近最少使用(淘汰最久不用的)
lfu:频率最少使用
一般会用allkeys-lru


6.集群


6.1主从同步


就是将一台主redis服务器的数据同步到多台从redis服务器上。


6.2哨兵


为了解决主从服务器宕机是需要手动恢复的问题。监控主从服务器并且自动恢复。


6.3Redis Cluster(集群)


去中心化,将数据分布在不同的服务器上,以此来降低系统对单主节点的依赖,从而提高redis的读写性能。
Redis Cluster方案采用哈希槽来处理数据和事例之间的映射关系(注意误区,这不是一致性hash算法),在Redis Cluster方案中,一个切片集群有16384个哈希槽,类似数据分区,每个键值对都会根据key被映射到一个哈希槽中,具体执行过程分为两大步:
1. 根据键值对的key,按照CRC16算法,计算一个16 bit的值。
2. 再用16bit值对16384进行取模,每个模数代表相应编号的哈希槽。

之后哈希槽被映射到具体的redis实例上有两个方案:
1. 平均分配:在使用cluster create命令创建redis集群时,redis会自动把所有哈希槽平均分配到集群实例上。比如有9个redis实例,那么每个redis上面的哈希槽个数是16384/9个。
2. 手动分配:可以使用cluster meet命令手动创建实例间的连接,组成集群,再使用cluster addslots命令指定每个实例上哈希槽的个数。
如图是2个redis实例,4个哈希槽时,键值对映射的关系。


6.4一致性hash


redis集群时3.0版本才出现的,出现的比较晚,在集群模式出现之前,很多公司都做了自己的redis集群了。这些自研的redis集群的实现方式有多种,比如在redis的jedis客户端jar包就是实现了一致性hash算法(客户端模式),或者在redis集群前面加上一层前置代理如Twemproxy也实现了hash一致性算法(代理模式)。



做法:
把服务器主机根据关键字(建议是主机名,因为ip会变)做hash运算并对2^32取模,得到服务器在hash环上的位置;然后存入值的key也hash运算2^32取模,顺时针遇到的第一个机器就是他要存放的位置。
缺点是,在机器A和C之间增加服务器D时,取值计算到了D,但D上面没有数据;服务器少时还会出现分布不均匀、数据倾斜。
解决办法是用虚拟节点,每台机器均匀地创建多个虚拟节点。


6.5总结


主从模式:master节点挂掉后,需要手动指定新的master,可用性不高,基本不用。

哨兵模式:master节点挂掉后,哨兵进程会主动选举新的master,可用性高,但是每个节点存储的数据是一样的,浪费内存空间。数据量不是很多,集群规模不是很大,需要自动容错容灾的时候使用。

集群模式:数据量比较大,QPS要求较高的时候使用。 Redis Cluster是Redis 3.0以后才正式推出,时间较晚,目前能证明在大规模生产环境下成功的案例还不是很多,需要时间检验。


7.其他杂记


7.1缓存三崩


缓存穿透——通过不存在的key穿透redis访问数据库。
解决办法:不存在的key也放入缓存,value为null;白名单;布隆过滤器。

缓存击穿——某个热点key过期后,大量此key请求造成击穿;
解决办法:热点数据永不过期;后台操控热点key,实时调整、监控;使用锁(只有一个线程可以操作热点数据),对性能不友好。

缓存雪崩——大量key在短时间内过期,都请求到数据库。
解决办法:预先对热门key进行设置过期时间;后台操控热点key,实时调整、监控;使用锁(只有一个线程可以操作热点数据),对性能不友好。


7.2redis和MySQL的数据一致性

todo


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值