最近在精进学习Redis,边学边写
php
先赞后读,养成习惯redis
预分配
冗余空间方式来减小
内存的频繁分配
最大长度
为 512M。SET expire60 "will expire in a minute" EX 60 # 设置值60秒后过时
复制代码
local_redis:0> mset name1 boy name2 girl name3 unknown
"OK"
local_redis:0> mget name1 name2 name3
1) "boy"
2) "girl"
3) "unknown"
复制代码
setex name 5 codehole # 5s 后过时,等价于 set+expire
复制代码
setnx name codehole # 若是 name 不存在就执行 set 建立
复制代码
自增是有范围的,它的范围是 signed long 的最大最小值,超过了这个值,Redis 会报错。shell
> set codehole 9223372036854775807 # Long.Max
OK
> incr codehole
(error) ERR increment or decrement would overflow
复制代码
一、验证码:常常在一些网站进行登陆、注册、获取验证码等操做的时候,都会收到一些验证码,而且说10min后失效。数据库
set phone_num code ex 600后端
用手机号做为key,验证码做为值,超时6min。这样当你输入好验证码,提交的时候,后台就能够了先get phone_num,再比较你的输入和数据库里面存的值,从而完成身份的验证。缓存
二、缓存功能:String字符串是最经常使用的数据类型,不只仅是redis,各个语言都是最基本类型,所以,利用redis做为缓存,配合其它数据库做为存储层,利用redis支持高并发的特色,能够大大加快系统的读写速度、以及下降后端数据库的压力。bash
三、计数器:许多系统都会使用redis做为系统的实时计数器,能够快速实现计数和查询的功能。并且最终的数据结果能够按照特定的时间落地到数据库或者其它存储介质当中进行永久保存。并发
四、bitmap位图:可普遍用于,签到、活跃、打卡等场景统计。灰常好用dom
五、分布式锁 确保分布式锁可用,咱们至少要确保锁的实现同时知足如下四个条件:分布式
PHP具体实现:
class RedLock {
private $retryDelay; // 重试间隔
private $retryCount; // 重试次数
private $clockDriftFactor = 0.01;
private $quorum;
private $servers = array();
private $instances = array();
function __construct(array $servers, $retryDelay = 200, $retryCount = 3) {
$this->servers = $servers;
$this->retryDelay = $retryDelay;
$this->retryCount = $retryCount;
$this->quorum = min(count($servers), (count($servers) / 2 + 1));
}
public function lock($resource, $ttl) {
$this->initInstances();
$token = uniqid();
$retry = $this->retryCount;
do {
$n = 0;
$startTime = microtime( true ) * 1000;
foreach ($this->instances as $instance) {
if ($this->lockInstance($instance, $resource, $token, $ttl)) {
$n++;
}
}
// 将 2 毫秒添加到漂移中,以考虑 Redis 过时精度,即 1 毫秒,加上小型 TTL 的 1 毫秒最小漂移。
$drift = ( $ttl * $this->clockDriftFactor ) + 2;
$validityTime = $ttl - ( microtime( true ) * 1000 - $startTime ) - $drift;
if ($n >= $this->quorum && $validityTime > 0) {
return [
'validity' => $validityTime,
'resource' => $resource,
'token' => $token,
];
} else {
foreach ( $this->instances as $instance ) {
$this->unlockInstance( $instance, $resource, $token );
}
}
// Wait a random delay before to retry
$delay = mt_rand( floor( $this->retryDelay / 2 ), $this->retryDelay );
usleep( $delay * 1000 );
$retry--;
} while ($retry > 0);
return false;
}
public function unlock(array $lock) {
$this->initInstances();
$resource = $lock['resource'];
$token = $lock['token'];
foreach ($this->instances as $instance) {
$this->unlockInstance($instance, $resource, $token);
}
}
private function initInstances() {
if (empty($this->instances)) {
foreach ($this->servers as $server) {
list($host, $port, $timeout) = $server;
$redis = new \Redis();
$redis->connect($host, $port, $timeout);
$this->instances[] = $redis;
}
}
}
private function lockInstance($instance, $resource, $token, $ttl) {
return $instance->set($resource, $token, ['NX', 'PX' => $ttl]);
}
private function unlockInstance($instance, $resource, $token) {
// 不但实现了 同一人加锁解锁;并且若是解锁不成功就回滚可以保证 资源的占用
$script = ' if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) else return 0 end ';
return $instance->eval($script, [$resource, $token], 1);
}
}
$servers = [
['127.0.0.1', 6379, 0.01],
];
$redLock = new RedLock($servers);
$i2Count = 0;echo '<pre>';
while ( $i2Count < 10 ) {
$lock = $redLock->lock('test', 10000);
if ($lock) {
print_r($lock);
$ret2Unlock = $redLock->unlock( $lock );
// !$ret2Unlock 则回滚全部操做
} else {
print "Lock not acquired\n";
}
$i2Count++;
}
复制代码
因为篇幅问题,此文章留下了问题
今明补上
参考阅读: