赞
踩
原则:
原因:
定义:同一时间大量的缓存失效导致数据库压力升高。
解决:随机过期时间保证同一时间不会有大量的key失效。
定义:访问一个数据库中不存在的值,由于每次在缓存中都查询不到会穿透到数据库中进行查询。
解决:缓存空值(最简单),或者引入布隆过滤器。接口基本的参数校验,比如过滤负值等等。
定义:热点key失效的瞬间大量读请求落到数据库上。
解决: 加锁让少量的请求来重构缓存,例如分布式锁或者读写锁、本地锁等等,粒度根据实际情况选择。
热点key不过期,只有写请求会重构缓存。 做缓存时间的续期。
一致性级别可以大致分为:最终一致性和强一致性。
当我们读请求变多以后,需要引入缓存来降低数据库压力,一次请求接口的过程大致如图所示。
当一个写请求过来应该怎么处理缓存呢?
缓存有两种处理方法:更新和删除,
如果有两个线程同时过来写同一个数据不一致情况如下图所示。
更新缓存的劣势:
结论: 不要对缓存进行更新。 不要对缓存进行更新。 不要对缓存进行更新。
当我们采用删除缓存时,应该先删还是后删呢?
「先更新数据库,再删除缓存」,默认情况下,短暂的不一致如图所示。
极端情况:如图所示,条件较为苛刻。
「先删除缓存,后更新数据库」
不一致的场景:在并发写读场景下,如图所示。
延迟双删:先删除缓存的方案可以改进一版,上述操作完成后休眠N毫秒后再次执行删除缓存。
到这里我们知道两种方案
方案二优点是:简单,无需引入额外的中间件,缺点是N毫秒不是特别好评估。
这两个方案的问题:无法保证缓存删除这一步一定可以成功。
比较合适的做法是:消息队列或订阅binlog中间件。
通过分布式锁,保障写请求更新的过程中没有读请求进来。
当数据库读写分离后,如果在主库写入后,从库同步前读取到的值就是旧值。
延迟双删可以一定程度的避免这个问题。
先更新数据库方案则需要评估同步时间和删除缓存谁快谁慢。
方案一:「先更新数据库,再删除缓存」。
方案二:「先更新数据库,再删除缓存,再删除缓存」。
并配合「消息队列」或「订阅变更日志」的方式来保证删除这一步的成功。
为什么有方案二:保证极端不一致。
如何从0到1构建一个稳定、高性能的Redis集群?(附16张图解)
现象:主从架构下,原先的主节点跟集群失去联系,从节点升级成为新的主节点,两个主节点都会写入数据。
主要思路:阻止原先的主节点写入数据。
解决方案:通过参数限制当主节点的从节点小于N值时,停止写入数据。
# min-slaves-to-write 3
# min-slaves-max-lag 10
https://redis.io/docs/management/sentinel/
min-replicas-to-write 1
min-replicas-max-lag 10
最大内存配置
maxmemory 100mb
https://redis.io/docs/reference/eviction/
LRU(least recently used )根据最近访问时间
LFU(least frequently used)根据访问频率
allkeys 是所有的key,volatile是带有过期时间的key。
4.0+支持 LFU 模式。
redis.windows.conf 中的示例
Windows下策略变更
config get maxmemory-policy
config set maxmemory-policy noeviction
config set maxmemory-policy volatile-ttl
redis 7.0.8 最大内存和淘汰策略
# maxmemory <bytes> # MAXMEMORY POLICY: how Redis will select what to remove when maxmemory # is reached. You can select one from the following behaviors: # # volatile-lru -> Evict using approximated LRU, only keys with an expire set. # allkeys-lru -> Evict any key using approximated LRU. # volatile-lfu -> Evict using approximated LFU, only keys with an expire set. # allkeys-lfu -> Evict any key using approximated LFU. # volatile-random -> Remove a random key having an expire set. # allkeys-random -> Remove a random key, any key. # volatile-ttl -> Remove the key with the nearest expire time (minor TTL) # noeviction -> Don't evict anything, just return an error on write operations. # # LRU means Least Recently Used # LFU means Least Frequently Used # # Both LRU, LFU and volatile-ttl are implemented using approximated # randomized algorithms. # # Note: with any of the above policies, when there are no suitable keys for # eviction, Redis will return an error on write operations that require # more memory. These are usually commands that create new keys, add data or # modify existing keys. A few examples are: SET, INCR, HSET, LPUSH, SUNIONSTORE, # SORT (due to the STORE argument), and EXEC (if the transaction includes any # command that requires memory). # # The default is: # # maxmemory-policy noeviction
RDB:只持久化某一时刻的数据快照到磁盘上(创建一个子进程来做)
AOF:每一次写操作都持久到磁盘(主线程写内存,根据策略可以配置由主线程还是子线程进行数据持久化)
RDB 采用二进制 + 数据压缩的方式写磁盘,这样文件体积小,数据恢复速度也快
AOF 记录的是每一次写命令,数据最全,但文件体积大,数据恢复速度慢
如果你的业务对于数据丢失不敏感,采用 RDB 方案持久化数据
如果你的业务对数据完整性要求比较高,采用 AOF 方案持久化数据
最佳实践
危害:
检测:
性能排查:
高消耗的命令,AOF频率,
CPU 相关:使用复杂度过高命令、数据的持久化,都与耗费过多的 CPU 资源有关
链路:nginx、分布式缓存、本地缓存、DB
https://www.cnblogs.com/Airgity/p/16741673.html
深入浅出java并发编程(ConcurrentHashMap)
<!-- https://mvnrepository.com/artifact/org.ehcache/ehcache -->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.10.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
https://github.com/ben-manes/caffeine
<!-- https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.2</version>
</dependency>
背景:在集群中实现一个用户数据存储的负载均衡,集群中有n个存储节点,如何均匀的把各个数据分布到这n个节点呢?,三台Redis如何尽可能高的提高缓存命中率。
原理:按照123123123的这种顺序循环存入。
优点:实现简单。
缺点:缓存命中率低,一个用户连续访问N次,会在3台Redis中都存储一份。
原理:按照机器数量进行取模,%3,%5
优点:如果机器数量稳定,缓存分布稳定。
缺点:当新增节点和删除节点的时候,会涉及大量的数据迁移问题
原理:系统中每个节点分配一个token,范围一般在0~232,这些token构成一个哈希环。数据读写执行节点查找操作时,先根据key计算hash值,然后顺时针找到第一个大于等于该哈希值的token节点,如图10-3所示。
优点:加入和删除节点只影响哈希环中相邻的节点,对其他节点无影响。
缺点:
现象:如果使用一致性哈希,会导致某台机器负载升高,不均匀。
解决方法:当访问不够均匀的时候将一致性HASH降级为取模。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。