web cache architecture and cache design

85
缓缓缓缓缓缓缓缓缓 缓缓缓 kim

Upload: ho-kim

Post on 08-Sep-2014

178 views

Category:

Technology


11 download

DESCRIPTION

Web cache architecture and cache design

TRANSCRIPT

Page 1: Web cache architecture and cache design

缓存架构与缓存设计

技术部 kim

Page 2: Web cache architecture and cache design

不讨论什么?

Page 3: Web cache architecture and cache design

• 软件安装和介绍

• 数据结构和源码细节

• 性能报告

Page 4: Web cache architecture and cache design

What is 缓存 ?

Page 5: Web cache architecture and cache design

• 处理速度差异的技术方法

• 缓存的快,都是相对的!

Page 6: Web cache architecture and cache design

缓存技术包括

Page 7: Web cache architecture and cache design

• 文件缓存( file cache )• 共享缓存( shared cache )• 软件内置缓存( local cache )• 缓存客户端( client cache )• CDN 缓存( cdn cache )• etc…

Page 8: Web cache architecture and cache design

重点说下 Client Cache

Page 9: Web cache architecture and cache design

• 被动更新• LRU 机制• 协议简单• 基于 libevent 非阻塞• 单点无冗余• 独立分布式,散列, O(1)

Page 10: Web cache architecture and cache design

Why use 缓存?

Page 11: Web cache architecture and cache design

• 减小负载• 减少阻塞、数据库查询、脚本执行• 让机器顺畅工作

Page 12: Web cache architecture and cache design

缓存架构

Page 13: Web cache architecture and cache design
Page 14: Web cache architecture and cache design

文件缓存

Page 15: Web cache architecture and cache design

• 优点:部署快,安全不丢失,易于拓展

• 缺点:无法应付并发, iNode 限制,磁盘短命,管理麻烦

Page 16: Web cache architecture and cache design

应用(一)

好友动态日志目录 /queue/all

Page 17: Web cache architecture and cache design

共享缓存

Page 18: Web cache architecture and cache design

• 优点:速度快,部署快、使用方便,运维更新和管理容易

• 缺点:服务器间不共享

Page 19: Web cache architecture and cache design

/dev/shm 共享

• 默认是真实内存的一半• 进程间共享数据• 物理内存缺乏时用 swap 交换数据• 支持动态在线调整• 无权限限制

Page 20: Web cache architecture and cache design

应用(一)

站内的登录秘钥: /dev/shm/secrectkey

Page 21: Web cache architecture and cache design

应用(二)

缓存 pfs 图片存储系统的查询结果: /dev/shm/pfs_domain

Page 22: Web cache architecture and cache design

内置缓存

Page 23: Web cache architecture and cache design

• 优点:速度快,无第三方依赖,无需另开端口

• 缺点:需要安装和配置,无法处理大缓存

Page 24: Web cache architecture and cache design

应用(一)

• PHP 的 APC : http://php.net/apc/

• 目标文件缓存( apc_compiler_cache )• 用户数据缓存( apc_user_cache )

Page 25: Web cache architecture and cache design

应用(二)-- Nginx 共享内存字典模块 : lua_shared_dict-- 缓存黑词local badwordslocal lcache = ngx.shared['lcache']if lcache then badwords = lcache:get(‘KEY_BADWORDS’)endif not badwords then local hc = self:_getHttpObj() badwords = hc:get('api.xxx.com', '/API/black_word') if badwords then lcache:set(‘KEY_BADWORDS’, badwords, 600) endend

Page 26: Web cache architecture and cache design

缓存客户端

Page 27: Web cache architecture and cache design

• 优点:服务期间共享,功能丰富,集群应用,适合大缓存处理

• 缺点: Socket 、带宽、内存消耗,数据丢失、安全隐患,部署和管理成本高

Page 28: Web cache architecture and cache design

Memcached

Page 29: Web cache architecture and cache design

• 90% 应用都有使用

• 历史悠久,性能、稳定性高

Page 30: Web cache architecture and cache design

应用(一)// 缓存状态值:$key = $account . '@reg_' . $regType;$userExist = $memd->Get($key);if (!$userExist) { $userLoginX = new UserLoginX(); $userExist = $userLoginX->checkExists($account); if ($userExist) { $memd->Put($key, "1", 10800); }}

Page 31: Web cache architecture and cache design

应用(二)// 缓存数据$cacheKey = md5('api@db_promo@2012' . $num);$videoList = $memd->Get($cacheKey);if (!$videoList) {

$data_json = Http::Get("api.xxx.com", ‘API/api_bd_list’);

if ($data_json) {$videoList = json_decode($data_json, true);$memd->Put($cacheKey, $videoList, 1800);

}}

Page 32: Web cache architecture and cache design

应用(三)// 计数器,发送限制,避免过于频繁发送信息$data = array ("startTime" => time (), "num" => $msgNum );$cache_key = "memKeyPreLimit" . $userid;$rs = $memd->Get ($cache_key);if (isset($rs) && is_array ( $rs )) { $startTime = $rs ["startTime"]; $num = $rs ["num"]; if ((time () - $startTime) < 900 && ($num + $msgNum < 30)) { $data = array ("startTime" => $startTime, "num" => $num + $msgNum ); }}$memd->Put($cache_key, json_encode( $data ), 900);

Page 33: Web cache architecture and cache design

应用(四)

保存 session ,比如站内验证码

Page 34: Web cache architecture and cache design

应用(五)// 缓存备份,多用于取接口数据的时候失败的时候不至于没数据显示$cacheKey = 'key_list_fresh';$backupKey = 'key_list_backup';$videoList = $memd->Get($cacheKey);if (!$videoList) {

$data_json = Http::Get(“api.xxx.com", 'API/list');if ($data_json) {

$videoList = json_decode($data_json, true);$memd->Put($cacheKey, $videoList, 1800);

$memd->Put($backupKey, $videoList, 86400); // 更新备份} else {

$videoList = $memd->Get($backupKey); // 接口取失败就取备份 }}

Page 35: Web cache architecture and cache design

TtServer

Page 36: Web cache architecture and cache design

• 5% 左右的应用在使用, comment 、 my 、fav 在使用

• 支持 Memcached 协议的 DBM 数据库,数据可持久化

Page 37: Web cache architecture and cache design

应用(一)// 取评论内容protected function _fetchContent($key){ $result = ''; $localConfig = $GLOBALS['scfg']['tt_server']; if (!$this->_dbContent) { $this->_dbContent = new Mem($localConfig); } $content = $this->_dbContent->Get($key); $result = sprintf('%s', json_decode($content)); if (json_last_error() != JSON_ERROR_NONE) { $result = sprintf('%s', json_decode(json_encode($content))); } return $result;}

Page 38: Web cache architecture and cache design

KtServer

Page 39: Web cache architecture and cache design

• 10% 左右的应用在使用,包括部分核心应用

• 高并发读写,持久化存储,故障恢复快

Page 40: Web cache architecture and cache design

应用(一)

• 视频拓展信息缓存集合(类似 redis hash 的实现)

Page 41: Web cache architecture and cache design

Redis

Page 42: Web cache architecture and cache design

• 50% 左右的应用使用

• 数据结构丰富,极适合并发高的复杂应用。极占内存,对开发人员要求较高。

Page 43: Web cache architecture and cache design

应用(一)// 用 incr 、 incrby 、 decr 、 decrby 实现计数器// 限制每 5秒投一票,每天投票总数是 90票$rc = $redis->get($rcKey);if (!$rc) { $redis->setex($rcKey, 1, 86400);}$rs = $redis->get($rKey);if ($rs === false && $rc < 90) { $redis->setex($rKey, 1, 5); $redis->incr($rcKey);} else { throw new Exception('留言速度太频繁啦! ');}

Page 44: Web cache architecture and cache design

应用(二)// 统计数字分段处理技术,对不同评论总数使用不同长度的缓存时间$total = $redis->get($rKey);if ($total === false) { $total = $obj->getTotal($id); if ($total > 300000) { $res = $redis->set($rKey, $total); } else if ($total > 99999) { $res = $redis->setex($rKey, $total, 86400 * 72); } else if ($total > 9999) { $res = $redis->setex($rKey, $total, 86400 * 6); } else { $res = $redis->setex($rKey, $total, 3600); }}

Page 45: Web cache architecture and cache design

应用(三)// lpush/ltrim/lpop/lrange 模拟有限队列,用户点播单列表:$listData = getUserDianBoList($userId);foreach ($listData as $data) { $count = $redis->LPush($uKey, $data); if ($count > MAX_RECORD_NUM_PER_LIST) { $redis->LTrim($uKey, 0, MAX_RECORD_NUM_PER_USER - 1); }}……$list = $redis -> lRange($uKey, 0, MAX_RECORD_NUM_PER_USER - 1);

Page 46: Web cache architecture and cache design

应用(四)-- 利用 hmset 实现实时记录最新更新的表:local rhkey = 'tb|updates'local hData = {}hData[tableIndex] = cjson.encode(currentTime)rds:hmset(rhkey, hData)……local tableRecords = rds:hgetall($rhkey);if tableRecords then .......end

Page 47: Web cache architecture and cache design

应用(五)-- 使用 hmget / hmset 实现正确的分页缓存-- 清理所有分页: rds:hclear(hlkey)local listlocal hlkey = 'hashlist|' .. vidlocal hlfield = orderby .. '|' .. numlocal hResult = rds:hmget(hlkey, hlfield)if hResult and hResult[1] then list = cjson.decode(hResult[1])else list = self:_getList(vid, orderby, num) local hData = {} hData[hlfield] = cjson.encode(list) rds:hmset(hlkey, hData)end

Page 48: Web cache architecture and cache design

应用(六)// 使用 zset 来实现自动排重 // 60秒内不能发表重复内容public function checkDuplicatedCnt($vid, $content){ $redis = self::getRedis(); $md5Cnt = md5($content); $rKey = ‘cnt|‘ . $vid; $isDuplicated = !$redis->sAdd($rKey, $md5Cnt); $redis->setTimeoutOnce($rKey, 60); return $isDuplicated; }

Page 49: Web cache architecture and cache design

应用(七)// 使用 zIncrBy 、 zRevRange 实现日排行榜功能: Top 20$rKey = 'toplist|' . date('md', time());$score = 1;$result = $redis->zIncrBy($rKey, $vid, $score);$redis->setTimeoutOnce($rKey, 86400);......$result = $redis->zRevRange($rKey, 0, 19);

Page 50: Web cache architecture and cache design

应用(八)-- 实时记录分表的最新更新时间及其顺序:local zsetData = {}local rzkey = ‘table|updated‘table.insert(zsetData, updated_at) -- 更新时间table.insert(zsetData, tablehash) -- 更新的表rds:zadd(rzkey, unpack(zsetData))……local withScore = true;local tableRecords = rds:zrevrange(‘table|updated’, 0, 1000, withScore);

Page 51: Web cache architecture and cache design

应用(九)-- 使用 pipeline 快速生成数据:rds:init_pipeline()local zsetData = {}local hashData = {}for k,v in pairs(tblVinfo) do -- 存进有序集备用 table.insert(zsetData, v['times']) table.insert(zsetData, v['id']) -- 存进哈希集备用 hashData[tostring(v['id'])] = cjson.encode(v)endrds:zadd(rzkey, unpack(zsetData))rds:hmset(rhkey, hashData) -- 用 mset/mget 一次设置 /获取多个值,优化性能rds:commit_pipeline()

Page 52: Web cache architecture and cache design

应用(十)// 用 MULTI 来实现事务,保证原子性// 想象一下假如同一时刻刚好有 2个进程都在执行 push 。。。$pipe = $redis->multi();foreach ($result['data'] as $value) { $len = $pipe->rPush($rKey, json_encode($value));}$pipe->setTimeout($rKey, 600);$pipe->exec();

Page 53: Web cache architecture and cache design

SSDB

Page 54: Web cache architecture and cache design

• 弹幕在试用,视频人气重构也在试用

• 使用 leveldb 做存储引擎,占内存极少。支持主主同步架构。绝大多数情况下可以替换掉 redis ,性价比极高。

Page 55: Web cache architecture and cache design

CDN 缓存

Page 56: Web cache architecture and cache design

• 优点:速度快

• 缺点:成本高

Page 57: Web cache architecture and cache design

应用(一)// 播放页针对视频不同状态,设置不同的 cdn 缓存时间if ($videoInfo['chk'] == 'n') { //未审核状态设置缓存时间 600S $cdnCacheTime = 600;} else { $cdnCacheTime = 259200;}header("Expires: " . gmdate("D, d M Y H:i:s", time() + $cdnCacheTime) . " GMT");header("Cache-Control: max-age=" . $cdnCacheTime);header("Last-Modified: " . gmdate("D, d M Y H:i:s", time()) . " GMT");if (ob_get_length()) { header("Content-Length: " . ob_get_length());}ob_end_flush();

Page 58: Web cache architecture and cache design

缓存代理 twemproxy

Page 59: Web cache architecture and cache design

• 70% 的应用在使用,构筑在客户端缓存与 应用之间,充当桥梁

• 轻量级,配置简单,支持 memcached ascii 和 redis 协议,多点长连接,高可用性

Page 60: Web cache architecture and cache design

关于缓存的技巧

Page 61: Web cache architecture and cache design

(一)区分对待查询结果

Page 62: Web cache architecture and cache design

• 查询成功,且数据不为空 -- 长缓存• 查询成功,但数据为空 -- 短缓存• 查询失败 -- 不缓存

Page 63: Web cache architecture and cache design

应用local res = db:findOne(sql)if type(res) == 'table' and res['id'] then rds:setex(key, cjson.encode(res), 3600)elseif db.lasterr == db.ERROR_NOT_FOUND then rds:setex(key, cjson.encode(res), 60)else -- 查询异常或者查询超时等情况end

Page 64: Web cache architecture and cache design

(二)缓存耦合

Page 65: Web cache architecture and cache design

• 优点:提升系统实时性,减少系统间依赖,增强系统稳定性

• 缺点:有违 RESTFUL 风格,修改和管理成本增加

Page 66: Web cache architecture and cache design

松耦合

Page 67: Web cache architecture and cache design

紧耦合

Page 68: Web cache architecture and cache design

(三)利用“用户”驱动

Page 69: Web cache architecture and cache design

• 利用接口 A 的访问,生成页面 B 的缓存

• 能共用一份缓存的时候,绝不使用两份

Page 70: Web cache architecture and cache design

一般的做法

Page 71: Web cache architecture and cache design

更好的做法

Page 72: Web cache architecture and cache design

终于,到总结了。。。

Page 73: Web cache architecture and cache design

1. 每一分内存都是宝贵的资源

Page 74: Web cache architecture and cache design

2. 缓存读写不一定比磁盘快

Page 75: Web cache architecture and cache design

3. 会过期的缓存才是好缓存

Page 76: Web cache architecture and cache design

4. 生产环境禁用 flush

Page 77: Web cache architecture and cache design

5. 严禁长 key

Page 78: Web cache architecture and cache design

6. 做好缓存校验

Page 79: Web cache architecture and cache design

最后你始终还有一个疑问。。。

Page 80: Web cache architecture and cache design

如何在适当的场合使用合适的缓存技术?

Page 81: Web cache architecture and cache design

1. 靠经验

Page 82: Web cache architecture and cache design

2. KISS原则

Page 83: Web cache architecture and cache design

3. 数据重要程度以及访问频度

Page 84: Web cache architecture and cache design

FAQ

Page 85: Web cache architecture and cache design

谢谢!