分布式缓存基础知识学习

一点点相对自己说的话

在以后的学习中希望自己能把思维导图画出来,因为图文结合非常不错.

开始吧

项目中为什么要用缓存呢?

  1. 高性能
    下面来一张图了解下缓存的用处
    一张图了解一下缓存的用处
  2. 高并发
    对于我来说,高并发这点确实经验不足,因为学校里面做过的项目总共也就用那么几台电脑,所以只能简单使用一下,真正要面对大量的QPS还是得在未来的项目中积累经验

项目中使用缓存可能会出现的问题

有缓存雪崩、数据库双写不一致、缓存击穿、缓存穿透、缓存并发竞争等等的问题,这些在项目中都需要考虑到,否则便是一个不合格的demo级别的项目,时刻面临亏损或者宕机的风险,这些问题在下文中会简单的回顾并提供一些的解决思路

了解一下Redis的单线程模型吧

一次客户端请求与Redis工作的流程
redis会与相互通信的客户端建立连接,监听相关的指令按顺序进行分发处理

为什么Redis是单线程的却能有如此高的性能呢?
原因可以归结为两点:

  1. 基于非阻塞的IO多路复用程序,该程序只负责监听socket连接中的各种请求并压入队列,不进行复杂的处理,所以非常迅速
  2. 基于内存的文件事件处理,因为纯内存,所以天生就是非常高效
  3. 单线程避免了多线程频繁上下文切换(依靠时间片分配cpu资源,每个线程获得一定时间的cpu使用时间,切换使用肯定会有一定的消耗)

Redis和Memcached的几个区别

  1. Redis单线程而Mem是多线程(缩写下)

  2. Redis支持更多的数据结构,包括字符串,散列,列表,集合,有序集,位图,超级日志和空间索引而Mem支持字符串和整数

    String 做缓存kv操作
    hash 可存储对象
    list 可做统计列表(如粉丝列表)lrange实现redis级别的高性能分页
    set 自动去重 可做交并差集
    sorted set 可进行排序

  3. Mem没有集群模式,需要实现只能往集群中分片写入,比较费事,而redis有原生的Redis Cluster(后面会介绍包括redis主从复制等相关知识)

  4. 小数据量Redis更优,100k以上的数据Mem更优,没有一个绝对的界定,机器性能也有关系,所以说主要的区别还是在于2和3两点吧

Redis过期策略

对于redis 的过期策略来讲当然离不开过期时间的设置,当键过期以后,redis会进行

定期删除+ 惰性删除的处理…

定期删除 : 默认100ms会从设置了过期时间的键中抽取部分进行检查并删除
惰性删除 : 少数未被抽取删除的过期键会在下一次被访问时删除并返回空

在这两个方式下redis可以保证一个过期了的键一定会被删除,但是删除归删除,如果定期删除太慢,而且不怎么进行访问key,还不断写入新key,那redis不就满了吗

答:走内存淘汰
内存淘汰有以下几个策略
1)noeviction (写满了再写就报错,差不多这意思,没啥人会用)
2)allkeys-lru (比较常用的算法,删除最少访问的key)
3)allkeys-random(所有键随机删,什么鬼东西)
4) volatile-lru(设置了过期事件的key中删除最少访问的key)
5) volatile-random (设置了过期键的随机删)
6) volatile-ttl(在设置了过期时间的key中删除有更早过期时间的key)

整体看下来肯定Lru策略比较符合正常人的口味

// Lru算法
public class LRUCache<K,V> extends LinkedHashMap<K,V>{

	private final int CACHE_SIZE;
	
	public LRUCache(int cacheSize){
		super((int)Math.ceil(cacheSize/0.75)+1,0.75f,true)
		//设置hashmap的初始大小,true是让linkedhashmap按照最近访问
		来排序,最近访问在头,最老访问在尾
		CACHE_SIZE = cacheSize;
	}

	@Override
	protected boolean removeEldestEntry(Map.Entry eldest){
		return  size() > CACHE_SIZE;
		//map中的数据量大于指定的缓存个数,就自动删除最老的数据
	}
	 
}

裂开…

Redis如何保证高可用

对于一般的项目而言,缓存可以基于Redis的主从架构部署实现读写分离

对于高数据量需求的项目可以使用集群一般来说Redis Cluster = Redis 主从架构(高并发)+ 持久化 + 哨兵保证高可用

简单的Redis主从架构

Redis必须进行持久化操作,如果不进行持久化,当master宕机后再重启,数据丢失,slave在同步数据后也都会丢失,100%!!! 虽然高可用机制中,slave node 可替换 master node继续工作, 但是不排除还未检测到master down便重新启动的情况 , 此时master数据已经100%丢失,还是有清空数据的风险

两种数据复制恢复策略

  1. RDB
    每隔几分钟或几小时几天,生成redis数据的一份完整的快照

    RDB快照的数据丢失:因为是每隔一段时间进行快照备份处理,如果宕机…

  2. AOF
    每秒调用操作系统的fsync,强制将os cache中的数据刷入磁盘文件中

    生成AOF文件存放每条写指令,当膨胀到一定程度后执行rewrite操作,会根据redis缓存中最新的数据进行构建

总结 : RDB适合做冷备份,AOF适合作为数据丢失的第一恢复策略

缓存雪崩、穿透、击穿

缓存雪崩:

下面放一张图来解释何为缓存雪崩

缓存雪崩

解决思路也用一张图来解决吧:

缓存雪崩的解决思路

  1. 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  2. 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
  3. 设置热点数据永远不过期。

缓存穿透

为恶意访问的结果,比如一秒有5000个请求,但其中有4000个是来自恶意访问,根本无法在redis查到缓存数据甚至mysql也无法查到因为根本不存在该数据,所以4000个恶意的请求会直接落至mysql,导致宕机

解决思路:

  1. 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  2. 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击

缓存击穿

缓存中无数据,数据库有数据,用户并发请求过高,可以尝试分布式锁,先放一个线程去获取数据,将数据添至缓存,然后释放锁,其他的线程即可通过缓存获取,锁的时间应该根据系统性能进行判断,不宜过长

  1. 缓存中有数据,直接返回数据
  2. 缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待100ms,再重新去缓存取数据。这样就防止都去数据库重复取数据,重复往缓存中更新数据情况出现。
  3. 当然这是简化处理,理论上如果能根据key值加锁就更好了,就是线程A从数据库取key1的数据并不妨碍线程B取key2的数据

双写不一致性问题

双写不一致,数据库与缓存中存储数据不同

进行一次数据更新时,先修改了数据库,再更新缓存, 但是在更新缓存时出现了某些问题,导致数据出现不一致的情况

初步解决,将操作顺序更换,即先删除缓存,然后更新数据库,即使更新数据库失败了,但起码数据库与缓存中的数据是一致的

在并发的情况下,写请求在修改一个数据的时候,可能会有一个读请求读取了数据,读取完后写操作才完成,那么又出现了双写不一致的情况

既然出现了先后交替的情况,自然可以想到将操作串行化进行解决

内存队列解决双写不一致
使用这样的方案进行处理时,应该注意读请求超时的情况,可以根据实际情况进行机器的增加,使每个内存队列分配的操作更少

Redis并发竞争问题

redis并发竞争问题
在Redis中进行写操作时,并发竞争问题是不可以忽视的,因为线程上下文切换导致写操作执行顺序不固定,具体情况如图

重点: 时间管理者 555555…

在进行并发问题解决时,只要争取的处理好时间戳,那么在数据新旧程度上的判断就非常轻松了

缓存架构问题该如何设计

例:redis cluster , 4台机器,2台部署主实例,2台部署从实例,每个主实例挂了一个从实例,2个节点提供读写服务,每个节点读写高峰达到每秒5W的QPS,2台机器是10W的QPS

机器配置 : 32G内核+8核cpu+1T磁盘,但是分配给redis的内存是10g,一般线上生产环境,redis的内存尽量不超过10g,超过10g会出问题

2台对外提供读写 , 一共有20g的内存

因为每个主实例都挂了一个从实例 , 所以是高可用的,任何一个主实例宕机都会自动故障迁移,redis从实例会自动变为主实例提供读写服务

内存写的一般是商品数据,每条大概是10KB,10万条1g。常驻内存的是100万条商品数据,占用内存20g不到

完结撒花*~

今天或许很菜,那明天至少不会比今天还菜,祝自己早点找到工作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL是一种开源的关系型数据库管理系统,是Web开发中最常用的数据库之一。以下是学习MySQL基础知识的几个关键点: 1. 数据库基础知识 你需要了解以下的基础知识: - 数据库的概念和特点 - 数据库管理系统(DBMS)和关系型数据库管理系统(RDBMS) - SQL语言的基础知识,包括SELECT、INSERT、UPDATE和DELETE等基本操作 2. 数据库设计 在设计数据库时,你需要考虑以下问题: - 数据库范式:数据库范式是一种规范化的设计方法,用于减少数据冗余和提高数据一致性。 - 数据库表的设计:如何分解数据,创建关联表以及定义主键和外键等。 - 数据库索引:索引可以提高数据库查询效率,你需要了解如何创建索引并选择正确的索引类型。 3. 数据库管理 在管理数据库时,你需要了解以下的内容: - 数据库安装和配置 - 数据库备份和恢复 - 数据库性能调整,包括查询优化、索引优化、缓存优化等。 - 数据库安全,包括用户管理、权限管理和数据加密等。 4. 数据库编程 在应用程序中,你需要使用编程语言来访问数据库。以下是一些你需要了解的内容: - 数据库连接:如何连接到数据库并执行SQL查询。 - 数据库事务:如何使用事务来保证数据的一致性。 - 数据库异常处理:如何处理数据库操作中可能出现的异常。 5. MySQL工具和技术 MySQL有许多工具和技术,可以帮助你更有效地管理和使用数据库,例如: - MySQL Workbench:一个用于管理和开发MySQL数据库的集成开发环境(IDE)。 - phpMyAdmin:一个用于管理MySQL数据库的Web界面。 - MySQL Cluster:一个用于处理大数据和高可用性需求的分布式数据库系统。 - MySQL Replication:一个用于复制MySQL数据的技术,用于实现数据备份和负载均衡等。 以上是MySQL基础知识的一些关键点,掌握这些知识可以帮助你更好地理解和使用MySQL数据库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值