欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Redis 理解

程序员文章站 2022-03-01 12:39:20
...

基于内存、可持久化的key-value非关系型数据库。

数据类型
①String、②List、③Hash、④Set、⑤ZSet。

持久化机制

RDB
每过一段时间执行一次写操作将内存数据写入磁盘,再在指定目录下生成一个rdb文件,写入成功后,替换之前的文件,用二进制进行压缩存储。

	优点:
		①:只会包含一个文件备份;
		②:相比于AOP机制,效率高。
	缺点:
		①:出现宕机,数据可能会丢失。

AOF
每次写、删除操作会记录到日志文件中,查询不会记录。重启根据日志文件恢复。

	优点:
		①:有更高的数据安全性;
		②:出现宕机,可采用redis-check-aof工具恢复,解决数据一致性问题;
		③:格式清晰、易理解,能更好的完成数据重建。
	缺点:
		①:数据文件大;
		②:运行效率低。

混合持久化
在redis4.0出现,将RDB文件内容和AOF文件内容存在一起,AOF日志不再是全量日志,只会记录从持久化开始->结束这段时间发生的增量AOF日志。

特点:
 	①:大量数据使用粗粒度(时间上)的rdb快照方式,性能高,恢复时间快。
	②:增量数据使用细粒度(时间上)的AOF日志方式,尽量保证数据的不丢失。

混合持久化是最佳方式吗?
不一定。混合持久化是Redis 4.0才引入的特性,现在很多 公司可能都还在使用3.x版本。使用不了这一特性。
另外,可以使用下面这种方式。Master使用AOF,Slave使用RDB快照,master需要首先确保数据完整性,它作为数据备份的第一选择;slave提供只读服务或仅作为备机,它的主要目的就是快速响应客户端read请求或灾切换。
至于具体使用哪种持久化方式,就看大家根据场景选择。没有最好,只有最合适。

过期策略

定期删除
按一定时间随机扫描(随机扫描:因为redis中key是成千上万的,全部扫描效率低,给cpu带来很大的负载)已经过期的key,将过期key放到独立字典中,定期遍历该字典进行删除。

惰性删除
客户端在访问key时,检测该key的过期时间是否过期,过期直接删除,无返回结果。

淘汰策略

有了过期删除策略,为什么还要有淘汰策略?
因为相对定期删除、惰性删除都会遗留大量过期key没删除(场景:“定期删除”随机扫描,可能会有已过期key未扫描到;“惰性删除”客户端请求完后,key过期,后期未请求,过期key存在遗留

①volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
②volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
③volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
④allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
⑤allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
⑥no-enviction(驱逐):禁止驱逐数据

分布式锁

分类

  1. Memcached:利用 Memcached 的 add 命令。此命令是原子性操作,只有在 key 不存在的情况下,才能 add 成功,也就意味着线程得到了锁。
  2. Redis:和 Memcached 的方式类似,利用 Redis 的 setnx 命令。此命令同样是原子性操作,只有在 key 不存在的情况下,才能 set 成功。
  3. Zookeeper:利用 Zookeeper 的顺序临时节点,来实现分布式锁和等待队列。Zookeeper 设计的初衷,就是为了实现分布式锁服务的。
  4. Chubby:Google 公司实现的粗粒度分布式锁服务,底层利用了 Paxos 一致性算法。

特性
①:一个方法在同一时间只能被一个机器的一个线程执行;
②:高可用的获取锁与释放锁;
③:高性能的获取锁与释放锁;
④:具备可重入特性;
⑤:具备锁失效机制,防止死锁;
⑥:具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。

redis锁

  1. 通过setnx命令的排他性来达成锁的互斥。setnx命令的特性是,在插入一个key、value对时,当key不存在时,可以设置成功,返回1,当key已经存在时,会设置失败,返回0。

  2. 通过锁超时来达成避免死锁的问题。当在Redis中插入key成功后,即认为获取锁成功,当锁使用完成后,需要删除相应key,即释放锁。当删除失败时,就会出现死锁问题。这时候,可以通过在set时,设置超时时间来解决。如设置超时时间为10s等。

  3. 通过独立线程来完成锁续租。由于加入了锁超时机制,所以,有可能会发生任务还未完成,锁就被释放的问题。一些分布式锁的开源框架,会通过一个单独线程,来不断通过exprie命令重刷key的过期时间,来达成一个锁续租的目的。

  4. 通过value来配合解决锁重入问题。在分布式锁下,value可以是当前进程或线程的一个唯一id,当获取锁时,如果发现锁已经存在,可以根据value值来判断,是否可以获取锁,来达成一个锁重入的目的。

优点:①性能好;②实现方便

缓存击穿
大量请求同时访问同一个key,key刚好失效,同一时间所有请求就会穿过缓存,直接请求数据库,数据库无法扛着这么大的并发,直接挂了。
解决办法:①加锁、②设置永不过期

缓存雪崩
比击穿更严重,大量key失效,直接请求数据库,数据库无法扛着这么大的并发,直接挂了。
解决办法:①将过期时间错开、②搭集群、③服务降级策略

缓存穿透
存在大量请求访问,同时大量key也不存在,直接请求数据库,数据库无法扛着这么大的并发,直接挂了。
解决办法:①将数据库查询为空丢到缓存,设置短时间过期时间、②业务规则过滤请求,采用布隆过滤器初始化key标识,检测不存在key,过滤非法请求

补充
实现分布式锁
数据库锁
基于数据库唯一索引,创建一个锁表,根据方法名字段建立唯一索引,执行某个方法,往表中插入一条数据形成加锁步骤,业务处理完成后删除数据,达到释放锁的目的。
问题及解决办法:
①基于数据库,数据库的可用性和性能直接影响分布式锁的性能和可用性。所以需要数据库双击部署、数据同步、主备切换;
②不具备可重入特性。需要单独列记录锁机器和线程信息;
③无锁失效机制。因为可能出现数据插入成功后,服务宕机,对应数据没有删除,服务恢复后一直无法删除,需要创建定时任务处理失效数据;
④不具备阻塞锁特性。获取不到锁直接失败,需要优化逻辑,循环多次获取;
⑤维护复杂。

ZooKeeper
为分布式应用提供一致性服务的开源组件,内部是一个分层的文件系统目录结构,规定同一个目录只能有一个唯一文件名。
①创建一个目录mylock;
②线程A获取锁就在mylock目录下创建临时顺序节点;
③获取mylock下所有子节点,再获取比自己小的兄弟节点,不存在,说明当前线程顺序号最小,获得锁;
④线程B获取所有节点,判断自己是否是最小节点,设置监听比自己次小的节点;
⑤线程A处理完,删除节点,线程B监听变更事件后,判断自己是不是最小的节点,如果是则获得锁。
优点:高可用、可重入、阻塞锁特性、可解决死锁问题。
缺点:需要频繁创建、删除节点,性能不如redis

相关标签: Redis redis