Skip to content

Commit ebabef2

Browse files
cache
1 parent 0a939f9 commit ebabef2

13 files changed

Lines changed: 215 additions & 11 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
* [ActiveMQ](https://github.com/apache/activemq)
7272
* [RabbitMQ](middle-software/RabbitMQ.md)
7373
* [Kafka](middle-software/kafka.md)
74-
* [RocketMQ](https://github.com/apache/incubator-rocketmq)
74+
* [RocketMQ](middle-software/RocketMQ.md)
7575

7676
* 缓存
7777
* [redis](open-source-framework/redis.md)

basic-knowledge/spring.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@
1313

1414

1515

16-
**简介:**
16+
#### 简介
1717

1818
一个应用非常广泛的java开源框架。主要分为两大块:IOC和AOP。
1919

2020

2121
`无论是技术类书籍或者网上资料、学习手册,非常多,此处就不详细列举`
2222

23-
### 事务
24-
25-
* [Spring事务传播性与隔离性](https://mp.weixin.qq.com/s/u4NLJ3I2vkeZHWBpgHsdEA)
26-
27-
### 其它
23+
#### 文档
2824

25+
* 事务
26+
* [Spring事务传播性与隔离性](https://mp.weixin.qq.com/s/u4NLJ3I2vkeZHWBpgHsdEA)
2927

3028
* annotation 重试配置
3129
* [Spring重试支持Spring Retry](http://blog.csdn.net/jiesa/article/details/76549381)
3230
* [https://stackoverflow.com/questions/38212471/springboot-retryable-not-retrying](https://stackoverflow.com/questions/38212471/springboot-retryable-not-retrying)
33-
* [Spring、Spring MVC、MyBatis 整合文件配置详解](https://mp.weixin.qq.com/s/8-XvEOA4WzrZwytOXpHHyw)
31+
32+
* 框架配置
33+
* [Spring、Spring MVC、MyBatis 整合文件配置详解](https://mp.weixin.qq.com/s/8-XvEOA4WzrZwytOXpHHyw)

basic-knowledge/springboot.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@
1010
* [代码热部署](springboot-hot-reload.md)
1111
* [eclipse中如何跑spring boot的单元测试](springboot-unit.md)
1212

13-
#### 学习资料
13+
#### 资料
1414

1515
* http://www.ityouknow.com/spring-boot
1616
* https://github.com/JeffLi1993/springboot-learning-example
1717
* https://github.com/spring-projects/spring-boot
1818
* http://www.jianshu.com/collection/f0cf6eae1754
1919
* http://zh.lucida.me/blog/java-8-lambdas-insideout-language-features/
20-
* 《SpringBoot揭秘--快速构建微服务体系》*
20+
* 《SpringBoot揭秘--快速构建微服务体系》
21+
* [Spring干货汇总](https://mp.weixin.qq.com/s/VFHmOIp-H4lgh4gQE-cj5A)
2122

2223

2324
---

middle-software/RabbitMQ.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@
1111
* [快速入门及应用](https://mp.weixin.qq.com/s/GIkzoIBGQJtXB9RXlwlzPQ)
1212
* [从入门到精通](http://blog.csdn.net/column/details/rabbitmq.html)
1313
* [RabbitMQ分布式集群架构](http://blog.csdn.net/woogeyu/article/details/51119101)
14+
* [有货RabbitMQ双活实践](https://mp.weixin.qq.com/s/GC2N1i27eAo8QFuzb6muJw)

middle-software/RocketMQ.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## RocketMQ
2+
----
3+
4+
5+
* [源代码](https://github.com/apache/incubator-rocketmq)
6+
7+
---
8+
9+
10+
* [分布式消息队列 RocketMQ 源码分析 —— Message 拉取与消费(上)](https://mp.weixin.qq.com/s/HUNuqsjj88vcNA_BzORBcg)
11+
* [分布式消息队列 RocketMQ 源码分析 —— Message 拉取与消费(下)](https://mp.weixin.qq.com/s/J4awuLHrBvSOphsUIAMV4A)
12+
* [分布式消息队列 RocketMQ 源码分析 —— Message 顺序发送与消费](https://mp.weixin.qq.com/s/hf0ywoRa6A0NKYGEGQL2BQ)

other/book.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,5 @@
129129
* 《金刚经·心经》
130130
* 《人生可以走直线》
131131
* 《没有做不到的事,只有不会做事的人》
132-
* 《货币战争》
132+
* 《货币战争》
133+
* 《自控力》

other/person.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* [职场“35岁危机”:这是我看过的最棒建议](https://mp.weixin.qq.com/s/TtOhnf7OcEwMOL5wc3DWqw)
1515
* [论三年内快速成长为一名技术专家](https://mp.weixin.qq.com/s/k6QeIzq3uL1pmmdnQB2AFg)
1616
* [快速成长为一名技术专家](https://mp.weixin.qq.com/s/a3X1J-TkJ3ThTdc0YCyIKw)
17+
* [美丽联合集团VP顶天:总结这一年,我们在技术上的变与不变](https://mp.weixin.qq.com/s/zMneLwJkhJ0jA96cIzxLKw)
1718

1819
---
1920
### 技术(P) --> 管理(M)

system-architecture/architecture-experience.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@
2727
### 缓存
2828

2929
* [cache相关](cache相关.md)
30+
* [cache经验总结](cache-summary.md)
3031
* [缓存架构之防雪崩设计](缓存架构之防雪崩设计.md)
3132
* [大型web系统数据缓存设计](https://mp.weixin.qq.com/s/Imn4FuXv2hw3uocgZsBlOg)
3233
* [cache常见的陷阱与坑](https://github.com/oldratlee/cache-practice)
34+
* [缓存穿透、缓存并发、热点缓存之最佳招式](https://mp.weixin.qq.com/s/62KJ2mSTGoUTPsq0RjU7lg)
35+
* [再谈缓存的穿透、数据一致性和最终一致性问题](https://mp.weixin.qq.com/s/kYXabyZhVthF-9rR0Uv4lQ)
3336

3437
### 高并发
3538

@@ -87,3 +90,4 @@
8790
* [好的架构是逐步演化过来的](http://mp.weixin.qq.com/s/KsFVTqDhYcO3Jws6oOoa4g)
8891
* [技术不应成为业务的工具](http://mp.weixin.qq.com/s?__biz=MjM5MDE0Mjc4MA==&mid=2650993402&idx=1&sn=f79a2e2cd75bf7ca539149addb6e7c21)
8992
* [创业公司如何打造高效的研发体系?](http://mp.weixin.qq.com/s/iGTJy98Fj_qT0gBMHxzH1g)
93+
* [那么贵的技术会议,真的能学到东西吗?](https://mp.weixin.qq.com/s/pf-2pw0W4vKch7IDGTyzBw)

system-architecture/architecture-good-case.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
* [点融支付系统架构的演进](https://mp.weixin.qq.com/s/823bGuLkU0uX-vHUYkr5jg)
5757
* [易宝支付日志中心平台建设](https://mp.weixin.qq.com/s/Lsw_Ygyp50IJnqjzHxpGWg)
5858
* [高并发支付场景分析及设计](https://mp.weixin.qq.com/s/syKnlmu_noyp0C4LeGp9Tw)
59+
* [中小型研发团队架构实践之企业支付网关](https://mp.weixin.qq.com/s/rfeFWOq--0FXRa6r1eritQ)
5960

6061

6162
---
@@ -222,6 +223,11 @@
222223
* ###### 微博
223224
* [新浪微博混合云架构如何轻松应对热点事件的高峰值流量](https://mp.weixin.qq.com/s/6tSbQFgSff07VIZRHpfTQg)
224225

226+
---
227+
#### 杂项
228+
229+
* ###### 会员、注册、登录
230+
* [单点登录怎么实现?](https://mp.weixin.qq.com/s/ZT1B6ziSSRW41FN33xA3ZA)
225231

226232
---
227233
#### 其它
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
## cache经验总结
2+
3+
---
4+
5+
### 为什么要使用cache
6+
7+
关系型数据库的数据量比较小,以mysql为例,单表的量尽量控制在千万级别。
8+
9+
关系型数据库在TPS上的瓶颈往往会比其他瓶颈更容易暴露出来,尤其对于大型web系统,由于每天大量的并发访问,对数据库的读写性能要求非常高;而传统的关系型数据库的处理能力确实捉襟见肘;以我们常用的MySQL数据库为例,常规情况下的TPS大概只有1500左右(各种极端场景下另当别论)。
10+
11+
下面是MySQL官方所给出的一份测试数据:
12+
13+
系统配置:
14+
15+
Sun V40z / 4x 2390MHZ / Solaris 10 / 8GB RAM
16+
17+
1m rows,Read Only,4 CPU
18+
19+
|Connections| Trans/sec |
20+
|--|--|
21+
|1|382|
22+
|2|677|
23+
|4|1130|
24+
|8|1479|
25+
|32|1418|
26+
|256|947|
27+
|1024|224|
28+
29+
[详细压测报告:](img/UC2005-Advanced-Innodb-Optimization.pdf)
30+
31+
https://www.percona.com/blog/files/presentations/UC2005-Advanced-Innodb-Optimization.pdf
32+
33+
对于一个PV上亿的网站,每一次请求涉及多次数据库交互,每天的读写请求量远远超过关系型数据库的处理能力,所以必须通过高效的缓存抵挡大部分的数据请求。
34+
35+
### 缓存类型
36+
37+
* 本地缓存
38+
39+
本地缓存会减少网络层的交互,无论是本地内存还是磁盘,速度比较快。但对分布式系统来讲有一个缺点,当数据库更新时,没有一个简单有效的方法去更新本地缓存。
40+
41+
**本地缓存适用两种场景:**
42+
43+
* 一、对缓存内容时效性要求不高,能接受一定的延迟,可以设置较短过期时间,被动失效更新保持数据的新鲜度。
44+
* 二、缓存的内容不会改变。比如订单号与uid的映射关系,一旦创建就不会发生改变。
45+
46+
**注意问题:**
47+
48+
* 内存Cache数据条目上限控制,避免内存占用过多导致应用瘫痪。
49+
* 内存中的数据移出策略
50+
* 虽然实现简单,但潜在的坑比较多,最好选择一些成熟的开源框架
51+
52+
* 分布式缓存
53+
54+
本地缓存的使用很容易让你的应用服务器带上“状态”,而且容易受内存大小的限制。
55+
56+
分布式缓存借助分布式的概念,集群化部署,独立运维,容量无上限,虽然会有网络传输的损耗,但这1~2ms的延迟相比其更多优势完成可以忽略。
57+
58+
优秀的分布式缓存系统有大家所熟知的Memcached、Redis。对比关系型数据库和缓存存储,其在读和写性能上的差距可谓天壤之别,redis单节点已经可以做到8W+ QPS。设计方案时尽量把读写压力从数据库转移到缓存上,有效保护脆弱的关系型数据库。
59+
60+
61+
* 客户端缓存
62+
63+
大部分的web应用、微服务应用都会尽量做到无状态,方便于线性扩容。有状态的后端存储:DB、NoSQL、分布式文件系统、CDN等。
64+
65+
另一个很重要的就是客户端缓存了,对客户端存储的合理使用,原本每天几千万甚至上亿的接口调用,一下就可能降到了几百万甚至更少,而且即便是用户更换浏览器,或者缓存丢失需要重新访问服务器,由于随机性比较强,请求分散,给服务器的压力也很小。另外再加上合理的缓存过期时间,就可以在数据准确和性能上做一个很好的折衷。
66+
67+
68+
### 常用技术框架
69+
70+
* Guave
71+
* Memcached
72+
* Redis
73+
74+
更多缓存框架:http://www.oschina.net/project/tag/109/cacheserver
75+
76+
### 更新策略
77+
78+
* 被动失效
79+
80+
缓存数据主要是服务读请求的,通常会设置一个过期时间,或者当数据库状态改变时,通过一个简单的delete操作,使数据失效掉;当下次再去读取时,如果发现数据过期了或者不存在了,那么就重新去数据库读取,然后更新到缓存中,这即是所谓的被动失效策略。
81+
82+
被动策略有一个很大的风险,从缓存失效到数据再次被预热到cache这段时间,所有的读请求会直接打到DB上,对于一个高访问量的系统,很容易被击垮。
83+
84+
85+
* 主动更新
86+
87+
主动更新,很容易理解,就是数据库存储发生变化时,会直接同步更新到Cache,主要是为了解决cache空窗期引发的问题。比如电商的卖家修改商品详情,具有读多写少特点。
88+
89+
但如果是读多写多,同样会带来另一个问题,就是并发更新。多台应用服务器同时访问一份数据是很正常的,这样就会存在一台服务器读取并修改了缓存数据,但是还没来得及写入的情况下,另一台服务器也读取并修改旧的数据,这时候,后写入的将会覆盖前面的,从而导致数据丢失。解决的方式主要有三种:
90+
91+
```
92+
1、锁控制。这种方式一般在客户端实现(在服务端加锁是另外一种情况),其基本原理就是使用读写锁,即任何线程要调用写方法时,先要获取一个排他锁,阻塞住所有的其他访问,等自己完全修改完后才能释放。如果遇到其他线程也在修改或读取数据,那么则需要等待。锁控制虽然是一种方案,但是很少有真的这样去做的,其缺点显而易见,其并发性只存在于读操作之间,只要有写操作存在,就只能串行。
93+
94+
2、单版本机制(乐观锁)。为每份数据保存一个版本号,当缓存数据写入时,需要回传这个版本号,然后服务端将传入的版本号和数据当前的版本号进行比对,如果等于当前版本号,则成功写入,否则失败。这样解决方式比较简单;但是增加了高并发下客户端的写失败概率;
95+
96+
3、多版本机制。即存储系统为每个数据保存多份,每份都有自己的版本号,互不冲突,然后通过一定的策略来定期合并,再或者就是交由客户端自己去选择读取哪个版本的数据。
97+
```
98+
99+
### 序列化
100+
101+
分布式缓存的本质就是将所有的业务数据对象序列化为字节数组,然后保存到自己的内存中。所使用的序列化方案也自然会成为影响系统性能的关键点之一
102+
103+
* 序列化速度
104+
* 对象压缩比例
105+
* 支持的序列化数据类型范围
106+
* 反序列化的速度
107+
* 框架接入易用性
108+
109+
常见的序列化框架:
110+
111+
* Java源生序列化
112+
* Hessian
113+
* Protobuf
114+
* Kryo
115+
116+
### 开发注意事项
117+
118+
* 评估当前业务使用的空间大小。避免空间不足,导致热数据被置换出去,影响缓存命中率
119+
* 不要把缓存当DB使用,因为它会丢失
120+
* 最好设置过期时间,可以自己回收
121+
* key定义遵循一定规则,相同业务采用同一前缀
122+
* 缓存对象粒度。高内聚低耦合,考虑尽可能复用,不要一个小字段修改导整个大对象全部失效
123+
124+
```
125+
方案一:
126+
uid---> 发过的贴子内容列表
127+
128+
方案二:
129+
uid--->发过的贴子tid列表
130+
tid--->贴子内容
131+
132+
```
133+
134+
* 另外缓存对象大小要控制,不要过大,占用过多带宽。之前遇到过一个业务团队,单key下挂了5M的大对象,每次用时,从缓存中取出,反序列化,然后取其中一小部分。后来随着业务并发量上升,把网卡打爆,进而影响其它正常业务访问。
135+
* 根据业务需求,选择合适的缓存框架,比如memcache只支持kv对存储,redis则支持较丰富的数据结构
136+
* 是否要引入多级缓存,本地内存--》非持久化缓存(如memcache)---》持久化缓存---》DB,要注意数据一致性问题
137+
* 提前考虑扩容问题
138+
139+
140+
### 问题汇总
141+
142+
##### 1、缓存穿透
143+
144+
我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容,如果不存在就直接查询数据库然后再缓存查询结果返回。这个时候如果我们查询的某一个数据在缓存中一直不存在,就会造成每一次请求都查询DB,这样缓存就失去了意义,在流量大时,可能DB就挂掉了。那这种问题有什么好办法解决呢?
145+
146+
有一个比较巧妙的做法是,可以将这个不存在的key预先设定一个值。比如,"NULL" ,在返回这个NULL值的时候,我们的应用就可以认为这是不存在的key。
147+
148+
缓存穿透如果被恶意攻击,造成的影响面很容易放大。比如文章详情页,查询一个不存在的tid,每次都会访问DB,如果有人恶意破坏,很可能直接对DB造成影响。
149+
150+
##### 2、缓存集体失效
151+
152+
对于一些活动期间的数据通常会提前预热到缓存中,并设置一个过期时间,如果系统的并发量很高,恰巧缓存又失效了,此时会将压力转嫁给后面的DB,很容易击垮系统。
153+
154+
那如何解决这些问题呢?
155+
156+
其中的一个简单方案就是将缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。还有一种方式,就是计算好缓存的过期时间。
157+
158+
##### 3、DB和缓存不一致
159+
160+
当修改了数据库后,没有及时修改缓存,或者缓存服务器挂了。如果是因为网络问题引起的没有及时更新,可以通过重试机制来解决。而缓存服务器挂了,请求首先自然也就无法到达,从而直接访问到数据库。那么我们在修改数据库后,无法修改缓存,这时候可以将这条数据放到数据库中,同时启动一个异步任务定时去检测缓存服务器是否连接成功,一旦连接成功则从数据库中按顺序取出修改数据,依次进行缓存最新值的修改。
161+
162+
##### 4、命中率较低,影响性能
163+
164+
* 过期时间太短, 这种场景可以根据实际情况适当增大过期时间
165+
* 存在不合理缓存删除逻辑, 导致有效的缓存频繁被删除
166+
* 不合理的key规则设计, 每次缓存访问的key都在变化, 导致无法命中缓存和频繁的新缓存创建
167+
* key确实不存在,但是应用还是在频繁的访问, 这种应该从业务逻辑上杜绝
168+
169+
### 性能指标
170+
171+
* 缓存空间的使用率
172+
* topN 命令的执行次数
173+
* 缓存的命中率
174+
* 缓存的接口平均RT,最大RT,最小RT
175+
* 缓存的QPS
176+
* 网络出口流量
177+
* 客户端连接数
178+
* key个数统计

0 commit comments

Comments
 (0)