缓存

Redis--分库快速写 与 Memcached--搜索纯读取

--use
网络(单线程|多线程)

--curd
内存(预分配--内存占用 | 实时申请--慢一点)
有效性(LRU--惰性失效 | expire--惰性+随机+暴力)
数据一致性(memcache cas  | redis 事务-Multi/Watch/Exec)
集群-分布式(consistent_hash | Twemproxy)

--save
数据备份(master-slave)
持久化(snapshot快照1/2和AOF-I/O) 
性能(被动访问和内存不够用 |pipeline script )

小结:内存+主从+读写
1. 要进行Master-slave配置,出现服务故障时可以支持切换,只在slave上配置数据持久化。
2. 当Redis物理内存使用超过内存总容量的3/5时就会开始比较危险了,就开始做swap,内存碎片大,物理内存+虚拟内存不足,这个时候dump一直死着,时间久了机器挂掉.当达到最大内存时,会清空带有过期时间的key,即使key未到过期时间.
3. redis与DB同步写的问题,先写DB,后写redis,因为写内存基本上没有问题

cache(kv ex):

* key - user:userid:9:email(表名:主键名:主键值:列名)   lisi@163.com  
 * val - 返回:个数|是否修改|存在性|类型|秒数 -1(已过期) -2(不存在);空字符串|旧值|头尾元素或中间元素|返回随机值
 * ex - mem指定 | redis可指定可不指定 ttl

redis:(单线程 申请内存 |  主从  持久化  多数据类型 事务 | 过期策略(惰性 随机 暴力)) 
持久化剖析:全量bgsave 写 磁盘,增量aof 刷 磁盘;aof支持修复;持久化的fork导致负载大==>主从(从备份和从切换)

mem(分布式consistent 缓存故障(雪崩-ex 无底洞-分布式 数据踢除-lru 命中-slab))
cache 命中:
memcached中新的value过来存放的地址是该value的大小决定的,value总是会被选择存放到chunk与其最接近的一个slab中,如果我的value是80b,那么我这所有的value总是会被存放到1号slab中,那么memcached会把这个slab中最近最少被使用的chunk中的数据清掉,然后放上最新的数据

问题:持久化+分布式
持久化, 复制和备份带来的系统和网络问题,无分布式方案导致软件设计的复杂度增加.
Redis 不适合作为海量数据存储方案. Redis 适合在数据规模较小, 性能要求较高的条件下应用

1.方法:
redis有全量(save/bgsave)和增量(aof)的持久化命令。 全量的原理就是遍历里所有的DB并写入dump.rdb文件。增量备份就是aof,每次执行命令后如出现数据变化把数据写到server.aofbuffer里,然后依照设置刷到磁盘上

2.区别:
快照db文件,优点是二进制,大小比aof日志文件小。但会丢失最后一次成功备份时间到down机时间的数据。
aof相比而言文件大小就大了点,但相对快照来讲,不大容易丢失文件。
目前redis检查数据文件是否有错对于快照及aof都能够支持,但修复则只对aof文件有效。

3.问题:
redis如果每60s更改记录数过万条就会dump(磁盘没闲着),而且是通过fork子进程dump(内存占用翻倍,cpu打满)。解决方法,可考虑把dump时间改为30m 有一次写修改就dump一次,而且主不dump,启动时只是download数据,不然的话加载数据前无法提供服务,dump交给从 
方式:

主从

备份:redis下同时存在aof和db备份文件,这时根据从redis是否支持aof来决定是否同步aof文件
slave->sync->master->bgsave->db
db->slave->ack
slave->(bgsave->ack期间新请求)->send->slave

切换:
slave  slave of no one  ->check or fix aof(下面2条) ->slave of master

./redis-check-aof /home/jbossas/Data/redis/redis-data/appendonly.aof
./redis-check-aof --fix /home/jbossas/Data/redis/redis-data/appendonly.aof

redis优化:当它们的元素数量及value大小小于某个限值时,会用(数组)来减少内存存储

redis zadd_push or multi
<?php

error_reporting(E_ALL);

ini_set('display_errors',1);

//1.zadd 有序集合实现队列

class RedisClient

{

const POSITION_FIRST = 0;

const POSITION_LAST = -1;

public $redis;

public function __construct(){

$this->redis = new redis();

$this->redis->connect('127.0.0.1', 6379);

}

public function testData()

{

$this->redis->zadd('msg', '0', 'lunch');

$this->redis->zadd('msg', '1', 'sleep');

$this->redis->zadd('msg', '2', 'run');

$this->redis->zadd('msg', '3', 'swim');

$this->redis->zadd('msg', '4', 'cinema');

}

public function zPop($zset)

{

return $this->zsetPop($zset, self::POSITION_FIRST);

}

public function zRevPop($zset)

{

return $this->zsetPop($zset, self::POSITION_LAST);

}

private function zsetPop($zset, $position)

{

$this->redis->watch($zset);

$element = $this->redis->zRange($zset, $position, $position);

if (!isset($element[0])) {

return false;

}

if ($this->redis->multi()->zRem($zset, $element[0])->exec()) {

return $element[0];

}

return $this->zsetPop($zset, $position);

}

//exmaple not use

public function mzadd($key, $scores, $vals){

$score_v = '';

foreach ($scores as $k => $v) {

$score_v .= ', '.$v.' , '.$vals[$k];

}

$score_v = substr($score_v, 1);

$lua = "return redis.call('zadd', '{$key}', {$score_v})";

if(!empty($score_v)){

$ret =  $this->redis->eval($lua);

}

return $ret;

}

}

//list

$redis = new RedisClient;

echo '<pre>';

$redis->testData();

while ($msg = $redis->zRevPop('msg')) {

print_R($msg);echo PHP_EOL;

}

$redis->testData();

while ($msg = $redis->zPop('msg')) {

print_R($msg);echo PHP_EOL;

}

//2.multi enhance profile

for ($i = 1; $i <= 10; $i++) {

$redis->redis->multi(Redis::PIPELINE);

for ($j = 1; $j <= 10; $j++) {

$msgid = ($i - 1) * 10000 + $j;

$userid = rand(0,100);

$redis->redis->sAdd('usr:msg', $msgid);

}

$redis->redis->exec();

}

$re = $redis->redis->smembers('usr:msg');

print_r($re);

//2.1 multi zadd

$vals = array(100=>'lunch2',101=>'sleep3',201=>'run4',301=>'swim5',401=>'cinema6');

$redis->redis->multi(Redis::PIPELINE);

foreach($vals as $score=>$val){

$lua = "return redis.call('zadd', 'mynewmsg', {$score},'{$val}')";

$ret =  $redis->redis->eval($lua);

}

$redis->redis->exec();

$msg = $redis->redis->zrange('mynewmsg',0,100);

echo '<pre>';

var_dump($msg);

?>

一、Redis

数据类型:
string 静态数据:存取
hash   属性数据:关系
set:去重数据:集合
list:列表数据:头尾
sort set    排序数据:先后

//存取 时效 加减1 键名操作 事务 持久化 
//get set setex setex delete mset mget getMultiple=>multi flushdb flushall     (ex nx m+)
//ttl persist setTimeout=>expire expireAt|                                              (+4)
//incr incrby decr decrby                                                                        (number)
//keys randomKey type dbsize rename renameNx move exists            (key use)

//curd +eists contain len 
//string:getSet get/setRange append strlen                           (get set)       
//hash h m/set m/get del keys vals getall len exists incrby    (field 0=>1 2=>3 4=>5 )                    
//list:l r push/x pop set get | l range/trim/rem/insert lsize |rpoplpush   (in out  range(save del get insert)  lists)
+
//set s add rem move pop sort inter/store union/store diff-前面的差集/store randMember members contains=>sismember size=>scared     (inter union diff | add rem  pop | member(contain size rand))
//zset z add rem |rev/range rem/rangebyscore score rank |count incrby size |union/inter(add and multiple)
(key score meber | score member | score member … ... )

zrank zrevrank==>排序的位数不同

zrank rank go
:4
zrevrank rank go
:2

zrange zrevrange =>展现多顺序不同

zrange rank 0 10
*7
$5
lunch
$5
sleep
$6
runner
$4
swim
$2
go
$4
jump
$6
paipai

zrevrange rank 0 10
*7
$6
paipai
$4
jump
$2
go
$4
swim
$6
runner
$5
sleep
$5
lunch

zrangebyscore zrevrangebyscore=>排序的大小不同

zrangebyscore rank 0 10
*7
$5
lunch
$5
sleep
$6
runner
$4
swim
$2
go
$4
jump
$6
paipai

zrevrangebyscore rank 10 0
*7
$6
paipai
$4
jump
$2
go
$4
swim
$6
runner
$5
sleep
$5
lunch

//multi(顺序处理) exec(执行) discard(丢弃) watch(乐观锁 不许改动) unwatch  pipeline(批处理)
//save bgsave lastsave bgrewriteaof slaveof info auth
//ttl -2 是过期了,-1是持久有效

//sort
sort key (desc) limit 0 5  
sort by  get  store

$r->setex('keys',3,'vals');
$r->getMultiple(array('key1','key2','key3','key4','key5'));
$r->setTimeout('x',30);
$r->linsert('list',Redis::BEFORE,'key1','def');
$r->sort('int',array('sort'=>'desc'));
$r->zscore('set','123');

//事务失败后不能回滚,造成部分执行完毕,事务只能保证操作的原子性,但不能保证数据原子性,因此采用乐观锁,watch/unwatch
$r->watch('num');
$r->multi();
$r->incrby('num',100);
$r->exec(); //or discard();
$num = $r->get('num');
// echo $num;

$r = new Redis;
$r->connect('127.0.0.1',6379);
$r->auth('password');
$r->ping();
$r->set('key','val');
$r->get('key');
$r->setnx('key','val');
$r->ttl('keys');
$r->delete('key');
$r->persist('keys');
$r->mset(array('key1'=>'val1','key2'=>'val2','key3'=>'val3','key4'=>'val4','key5'=>'val5'));
$r->exists('key2');
$r->incr('num');
$r->incrby('num',10);
$r->flushDB();
$r->flushAll();
$r->randomKey();
$r->select(0);
$r->move('x',1);
$r->rename('name','myname');
$r->renameNx('myname','myname2');
$r->expireAt('x',time());
$r->keys('*');
$r->dbSize();

$r->bgrewriteaof();
$r->slaveof('127.0.0.1',6380);
$r->save();
$r->bgsave();
$r->lastSave();
$r->info();
$r->type('myname'));

//string
$r->set('string','str');
$r->strlen('string');
$r->append('string','insert');
$r->get('string');
$r->getSet('string','abc');

//hash
$r->hmset('student',array('wangming'=>80,'xiaohong'=>85,'ligang'=>90));
$r->hdel('student','ligang');
$r->hmget('student',array('xiaohong','wangming'));
$r->hget('student','xiaohong');
$r->hexists('student','wangming');
$r->hlen('student');
$r->hincrBy('student','xiaohong',10);
$r->hget('student','xiaohong');
$r->hkeys('student');
$r->hvals('student');
$r->hgetall('student');

//list
$r->lpush('list','key1');

$r->linsert('list',Redis::BEFORE,'key1','def');

$r->lrange('list',0,-1);
$r->ltrim('list',2,10);
$r->lsize('list');
$r->lget('list',0);
$r->rpoplpush('list','list2');

//set
$r->sadd('set',123);
$r->srem('set',789);
$r->smove('set2','set','789');
$r->smembers('set');
$r->spop('set2');
$r->ssize('set');
$r->scontains('set','456');
$r->srandMember('set');

$r->sort('int',array('sort'=>'desc'));

$r->sinter('int','int2');
$r->sunion('int','int2');
$r->sdiff('int2','int');
$r->sdiffstore('diffstore','int2','int');
$r->smembers('diffstore');

//zset
$r->zadd('set',0,'123');
$r->zcount('set',0,42);
$r->zsize('set');
$r->zincrby('set',2000,'123');
$r->zremrangeByScore('set',0,1);

$r->zscore('set','123');

$r->zrank('set','789');
$r->zRevrange('set',0,-1);

二、Memcached +pipe+bykey+cas | Memcache connect(8个)

// append prepend getDelayed fetch fetchall setMulti getMulti addServers getServerByKey setByKey cas--写锁的set setOptions
//set = add replace
$m = new Memcached();
$m->addServer('127.0.0.1',11211);
$m->set('foo','bar');
$m->setOption(Memcached::OPT_COMPRESSION,false);
$m->append('foo','def');
$m->prepend('foo','000');
$m->get('foo');
$m->getServerList();
$m->setByKey('127.0.0.1','orderKey',1);
$server = $m->getServerByKey($key);
$m->fetchAll();

$m->getDelayed(array('int','string'),true);
 while ($re = $m->fetch()) {

}

$m->setMulti(array('key1'=>'val1','key2'=>'val2','key3'=>'val3'),true);
$m->getMulti(array('key1','key2','key3'),$cas);

$m->addServers(array(
array('127.0.0.1',11211),
array('127.0.0.1',11212)

));

do {
$ips = $m->get('ip_block',null,$cas);//加上$cas后面才能用
if ($m->getResultCode()==Memcached::RES_NOTFOUND) {
$ips = $_SERVER['REMOTE_ADDR'];
$m->add('ip_block',$ips);
}else{
$m->cas($cas,'ip_block',$ips);//加了写锁的set
}
} while ($m->getResultCode()!=Memcached::RES_SUCCESS);

var_dump($ips);

三、Memcache
set(key,val,compress,timeout) get delete flush flush_all close add replace
new connect
increment decrement
addServer(host,port,persist,weight,timeout,retry_intval,status,failecallback)

./memcached -m 256 -c 1000 -P -l 127.0.0.1 -p 11211 -u root -d /tmp/memcached.pid

getVersion getStats hit/cmd.. getExtendedStats getStatus

redis+mc review相关推荐

  1. matlab预测未来gdp,matlab对国内生产总值(GDP)建立马尔可夫链模型(MC)并可视化...

    混合图 可以通过在有向图中绘制目标概率和预期的第一次命中时间来可视化. 从马尔可夫链中的每个状态开始计算命中目标状态的指定子集的概率.其中节点颜色表示命中概率. 绘制马尔可夫链的有向图,其中节点颜色表 ...

  2. redis客户端连接数量_redis设置并发连接数 如何合理设置连接池的大小 - Redis - 服务器之家...

    redis设置并发连接数 如何合理设置连接池的大小 发布时间:2017-04-28 来源:服务器之家 先看几个问题,再看具体内容: 1) 为什么要合理设置连接池的大小 2) 服务器端的连接配置.最大允 ...

  3. 大型分布式系统中的缓存架构

    作者:陈彩华 来自:51cto技术栈(ID:blog51cto) 本文主要介绍大型分布式系统中缓存的相关理论,常见的缓存组件以及应用场景. 缓存概述 缓存概述 缓存的分类 缓存主要分为四类,如下图: ...

  4. 如何设计一个小而美的秒杀系统?

    https://www.ibm.com/developerworks/cn/web/wa-design-small-and-good-kill-system/index.html 现如今,春节抢红包的 ...

  5. 理解分布式系统中的缓存架构(下)

    承接上一篇<理解分布式系统中的缓存架构(上)>,介绍了大型分布式系统中缓存的相关理论,常见的缓存组件以及应用场景,本文主要介绍缓存架构设计常见问题以及解决方案,业界案例. 1. 分层缓存架 ...

  6. oom 如何避免 高并发_微博短视频百万级高可用、高并发架构如何设计?

    本文从设计及服务可用性方面,详细解析了微博短视频高可用.高并发架构设计中的问题与解决方案. 今天与大家分享的是微博短视频业务的高并发架构,具体内容分为如下三个方面: 团队介绍 微博视频业务场景 &qu ...

  7. 深入理解分布式系统中的缓存架构(下)

    转载自   深入理解分布式系统中的缓存架构(下) 承接上一篇<理解分布式系统中的缓存架构(上)>,介绍了大型分布式系统中缓存的相关理论,常见的缓存组件以及应用场景,本文主要介绍缓存架构设计 ...

  8. 快速掌握:大型分布式系统中的缓存架构

    关注我们获得更多内容 " 本文主要介绍大型分布式系统中缓存的相关理论,常见的缓存组件以及应用场景. 缓存概述 缓存概述 缓存的分类 缓存主要分为四类,如下图: 缓存的分类 CDN 缓存 CD ...

  9. 如何设计一个抢红包系统(商品秒杀同理)

    参考资料:https://www.jianshu.com/p/c4a743bbe3a4 这种情况下要解决的问题: 同一时间同时进行抢购,网站瞬时访问流量激增. 访问请求数量远远大于库存数量,但是只有少 ...

  10. Saas发展史常用架构

    一.什么是Saas?   从字面中理解SaaS的全称是Software as a service, 即软件即服务,即由传统的开发卖软件升级到开发软件卖服务.百度百科对SAAS的定义是:SAAS平台是运 ...

最新文章

  1. 开源wkhtmltopdf使用心得 (一)
  2. Metaphors for a richer understanding of software development -- Code complete reading notes(2)
  3. 在linux下,如何在C语言中使用正则表达式
  4. Java虚拟机 —— 运行时数据区
  5. 调整xfce中的鼠标大小到48以上-目前还没有完成
  6. 并不对劲的bzoj5475:loj2983:p5206:[wc2019]数树
  7. linux系统export,Linux入门进阶 - 如何在Linux中使用export命令
  8. [Leetcode][第1025题][JAVA][除数博弈][数学][递推]
  9. 数据库冷备份和热备份
  10. js获取request中的值_基于node.js的开发框架 — Koa
  11. srs2.0安装问题
  12. 【Axure】Axure RP 9 下载、短期试用破解安装和汉化步骤 —— 可供安装参考,短期试用,目前授权码已逐渐失效
  13. 转:大前研一:“质问力”是解决问题最重要的能力
  14. 计算机里没有usb驱动设备,USB驱动,电脑没有usb驱动怎么办
  15. 【C++决赛】2019年全国高校计算机能力挑战赛决赛C++组题解
  16. exlsx表格教程_e某cel表格~的各种基本操作.doc 文档全文预览
  17. RTX 3060 快速配置GPU版本tensorflow
  18. 计算机主机硬件图片,电脑主机里的各个硬件名称图片用途和使用说明
  19. 从Oracle收购Sun 公司谈起
  20. JavaScript内部原理实践——真的懂JavaScript吗?(转)

热门文章

  1. Altium_Designer不规则焊盘制作
  2. Rasa开发使用 Rasa_NLU及Rasa_Core模型训练与测试
  3. 计算机网络基础学习笔记
  4. iOS15适配本地通知功能
  5. 【Idea】换行快捷键
  6. GPT生成情人节表白情话,AI撩骚情人卡很搞笑!
  7. 为公司添加以网站作为邮箱后缀的企业邮箱
  8. 如何关闭机房迦卡他卡进程,让你轻松上网。
  9. PAT A 1034
  10. 学习笔记-测试利器Mocha