开发成长之路(19)-- 缓存中间件:redis_数据库

 

文章目录

    • 关于redis
    • redis.conf翻译与配置
    • 缓存穿透
    • 缓存雪崩
    • 缓存击穿(热点数据集中失效)
    • 数据一致性
    • 以上解决方案
    • Centos下安装redis
    • 主从复制
      • “主从复制” ,存在即合理
      • 使用简明教程:
    • redis集群
      • redis集群的数据分片
      • Redis 集群的主从复制模型
      • Redis 一致性保证

 

关于redis

关于redis,我还是写了不少的。

什么是redis?

是一个NOSQL类型数据库,
是一个高性能的key-value数据库,
是为了解决高并发、高可用、大数据存储等一系列的问题而产生的数据库解决方案,
是一个非关系型的数据库,
但是,它也是不能替代关系型数据库,只能作为特定环境下的扩充。

没有用redis时,服务器对数据库的访问情况是这样的:
开发成长之路(19)-- 缓存中间件:redis_数据库_02

用了redis之后,服务器对数据的访问是这样的:
开发成长之路(19)-- 缓存中间件:redis_数据库_03


redis.conf翻译与配置

博主不辞辛劳翻译了一下redis.conf配置文件,感觉里面东西还是挺好的。
redis.conf翻译与配置(一)【redis6.0.6】
redis.conf翻译与配置(二)【redis6.0.6】
redis.conf翻译与配置(三)【redis6.0.6】
redis.conf翻译与配置(四)【redis6.0.6】
redis.conf翻译与配置(五)【redis6.0.6】
redis.conf翻译与配置(六)【redis6.0.6】
翻译亦是不易,大家多多支持


缓存穿透

业务系统要查询的数据根本就存在!当业务系统发起查询时,按照上述流程,首先会前往缓存中查询,由于缓存中不存在,然后再前往数据库中查询。由于该数据压根就不存在,因此数据库也返回空。这就是缓存穿透。

如果存在海量请求查询压根就不存在的数据,那么这些海量请求都会落到数据库中,数据库压力剧增,可能会导致系统崩溃(你要知道,目前业务系统中最脆弱的就是IO,稍微来点压力它就会崩溃,所以我们要想种种办法保护它)。

那么我们现在再来想想,为什么需要用缓存。答案已经很明显了,不用缓存,相当于直接击穿。


缓存雪崩

通过上文可知,缓存其实扮演了一个保护数据库的角色。它帮数据库抵挡大量的查询请求,从而避免脆弱的数据库受到伤害。

开发成长之路(19)-- 缓存中间件:redis_数据库_04

如果缓存因某种原因发生了宕机,那么原本被缓存抵挡的海量查询请求就会像疯狗一样涌向数据库。此时数据库如果抵挡不了这巨大的压力,它就会崩溃。

这就是缓存雪崩。


缓存击穿(热点数据集中失效)

其实理解了前面的缓存穿透和缓存雪崩之后,就很好理解缓存击穿了。

如果某一个热点数据失效,那么当再次有该数据的查询请求时就会前往数据库查询。但是,从请求发往数据库,到该数据更新到缓存中的这段时间中,由于缓存中仍然没有该数据,因此这段时间内到达的查询请求都会落到数据库上,这将会对数据库造成巨大的压力。此外,当这些请求查询完成后,都会重复更新缓存。


数据一致性

读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存和数据库间的数据一致性问题。不管是先写数据库,再删除缓存;还是先删除缓存,再写库,都有可能出现数据不一致的情况。举个例子:

1、如果删除了缓存Redis,还没有来得及写库MySQL,另一个线程就来读取,发现缓存为空,则去数据库中读取数据写入缓存,此时缓存中为脏数据。
2、如果先写了库,在删除缓存前,写库的线程宕机了,没有删除掉缓存,则也会出现数据不一致情况。

因为写和读是并发的,没法保证顺序,就会出现缓存和数据库的数据不一致的问题。如何解决?


以上解决方案

以上这些概念,都缺少一个解决方案,不是不放,实在是解决方案太长篇大论了。
带上问题来学redis,看到不吃亏(什么是redis?缓存问题、数据一致性、redis配置文件汉化版)


讲了这么多,接下来该上手实操了啊。


Centos下安装redis

【redis入门】Centos下安装redis
【redis入门】redis安装后相关知识串讲


主从复制

这个概念以前没有接触过,学了redis之后才接触到,觉得非常的不错。

开发成长之路(19)-- 缓存中间件:redis_redis_05

在Redis集群中,让若干个Redis服务器去复制另一个Redis服务器,我们定义被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(slave),这种模式叫做主从复制模式。

数据流向是单向的,只能是从master到slave
一个slave只能有一个master

“主从复制” ,存在即合理

为数据提供多个副本,实现高可用(容灾备份)
实现读写分离(主机负责写数据,从机负责读数据,主机定期把数据同步到从机保证数据的一致性)

使用简明教程:

1)配主不配从
2)配置命令:SLAVE 主机IP 主机Port
每次与主机断开之后,都要重新连接,除非修改配置文件。
3)详细操作

1.拷贝多个redis.conf文件
2.开启daemonize yes
3.pid文件名字
4.指定端口
5.log文件名字
6.dump.rdp名字

操作流程:【redis】跟我一起动手玩玩redis主从复制和哨兵模式


redis集群

什么是中心化?简单点说就是“中央集权”。
前面所说主从模式,一主二仆,主机一挂,全线瘫痪,虽然有哨兵盯着,扶持主机上位,仍然是麻烦。而且数据规模一旦庞大,中心化就很危险。

开发成长之路(19)-- 缓存中间件:redis_数据库_06

一个应对方法,就是去中心化。
开发成长之路(19)-- 缓存中间件:redis_原力计划_07

在redis的应用场景下,就是集群分布。
本篇为Redis集群的一般介绍,没有涉及复杂难懂的分布式概念的赘述。

 

1)Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。

2)Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.

3)Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令. Redis 集群的优势:

自动分割数据到不同的节点上。
整个集群的部分节点失败或者不可达的情况下能够继续处理命令。

redis.conf中关于集群的介绍:redis.conf翻译与配置(五)传送门

redis集群的数据分片

Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念.

Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:

节点 A 包含 0 到 5500号哈希槽.
节点 B 包含5501 到 11000 号哈希槽.
节点 C 包含11001 到 16384号哈希槽.

这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中得部分槽到D上. 如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.

Redis 集群的主从复制模型

为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品.

在我们例子中具有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用.

然而如果在集群创建的时候(或者过一段时间)我们为每个节点添加一个从节点A1,B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了

不过当B和B1 都失败后,集群是不可用的.

Redis 一致性保证

Redis 并不能保证数据的强一致性. 这意味这在实际中集群在特定的条件下可能会丢失写操作.

第一个原因是因为集群是用了异步复制. 写操作过程:

客户端向主节点B写入一条命令.
主节点B向客户端回复命令状态.
主节点将写操作复制给他得从节点 B1, B2 和 B3.

主节点对命令的复制工作发生在返回命令回复之后, 因为如果每次处理命令请求都需要等待复制操作完成的话, 那么主节点处理命令请求的速度将极大地降低 —— 我们必须在性能和一致性之间做出权衡。 注意:Redis 集群可能会在将来提供同步写的方法。 Redis 集群另外一种可能会丢失命令的情况是集群出现了网络分区, 并且一个客户端与至少包括一个主节点在内的少数实例被孤立。

举个例子 假设集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六个节点, 其中 A 、B 、C 为主节点, A1 、B1 、C1 为A,B,C的从节点, 还有一个客户端 Z1 假设集群中发生网络分区,那么集群可能会分为两方,大部分的一方包含节点 A 、C 、A1 、B1 和 C1 ,小部分的一方则包含节点 B 和客户端 Z1 .

Z1仍然能够向主节点B中写入, 如果网络分区发生时间较短,那么集群将会继续正常运作,如果分区的时间足够让大部分的一方将B1选举为新的master,那么Z1写入B中得数据便丢失了.

注意, 在网络分裂出现期间, 客户端 Z1 可以向主节点 B 发送写命令的最大时间是有限制的, 这一时间限制称为节点超时时间(node timeout), 是 Redis 集群的一个重要的配置选项。