Redis分布式锁

分布式锁

在这里插入图片描述
代码实现:

加锁与解锁:

<?php
namespace App\Services;

use Illuminate\Support\Facades\Redis;

class RedisLockService
{
    const LOCK_SUCCESS = 'OK';
    const IF_NOT_EXISTS = 'NX'; //代表只在键不存在时,才对键进行设置操作。键存在不能设置值
    const MILLISECOND_EXPIRE_TIME = 'EX'; //过期时间
    const EXPIRE_TIME = 50; // millisecond => 50s

    /**
     * @param $key
     * 加锁
     */
    public function lock($key,$uuid,$expire_time = '')
    {
        if (empty($expire_time)){
            $expire_time = self::EXPIRE_TIME;
        }
        $ret = Redis::set($key,$uuid,self::MILLISECOND_EXPIRE_TIME , $expire_time,self::IF_NOT_EXISTS); //不用setnx 避免死锁,setnx不能设置过期时间
        if ($ret == self::LOCK_SUCCESS){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 释放锁
     */
    public function unlock($key,$uuid)
    {
        $lua =<<<LUA_SCRIPT
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end
LUA_SCRIPT;
        $restful = Redis::eval($lua,1,$key,$uuid);
        return $restful;
    }
}
?>
<?php
public function DistributedLock($id)
{
    $RedisLock = new RedisLockService();
    $key = "product_".$id;
    $uuid = Uuid::uuid1($id);
    $uuid = $uuid->getHex();
    $return = "";
    try{
        if (!$RedisLock->lock($key,$uuid)){
            return "当前业务繁忙,请稍后";
        }else{
            $ret = DB::table("fm_products")->where("id",$id)->first();
            if ($ret->store >0){
                $ret = DB::table("fm_products")->where("id",$id)->decrement("store");
                if ($ret){
                    $return =  "下单成功";
                }else{
                    $return =  "下单失败";
                }
            }else{
                $return =  "库存不足";
            }
            $RedisLock->unlock($key,$uuid);
            return $return;
        }
    }catch (\Exception $exception){
        $RedisLock->unlock($key,$uuid);
        return $exception->getMessage();
    }

}
?>

内存淘汰策略

定期删除,指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除

惰性删除,获取某个key的时候,redis会检查一下 ,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。

其他

volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
allkeys-lru:从数据集中挑选最近最少使用的数据淘汰

volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
no-enviction(驱逐):禁止驱逐数据,这也是默认策略

多级缓存

Openresty安装

安装依赖
yum install readline-devel pcre-devel openssl-devel

获取安装包解压
wget https://openresty.org/download/ngx_openresty-1.9.7.1.tar.gz # 下载
tar xzvf ngx_openresty-1.9.7.1.tar.gz # 解压

进入安装目录,编译安装
cd ngx_openresty-1.9.7.1/
./configure
make
make install

使用Openresty-创建lua脚本

ngx.header.content_type="application/json;charset=utf8"
local cjson = require("cjson")       --引入模块
local mysql = require("resty.mysql")     --引入mysql模块
local uri_args = ngx.req.get_uri_args()
local product_id = uri_args['product_id']
local db = mysql:new()             --初始化数据库
db:set_timeout(1000)             --设置超时时间
local props = {
host = "192.168.29.108",            --mysql ip地址
port = 3306,                 --mysql  端口
database = "starsky",                     --mysql 数据库
user = "starsky", password = "root"     --用户名密码
}
local res = db:connect(props)         --获得mysql连接
local select_sql = "select id,store from fm_products where id ='"..product_id.."'"                 --一条查询语句
res = db:query(select_sql) db:close()     --执行
local redis = require("resty.redis")     --引入redis
local red = redis:new() red:set_timeout(2000)     --初始化 设置超时时间
local ip ="192.168.29.108"
local port = 6379
red:connect(ip,port)
red:auth("root")
red:set("product_"..product_id,cjson.encode(res))      --存储到redis
red:close()
ngx.say("{flag:true}")
ngx.header.content_type="application/json;charset=utf8"
local uri_args = ngx.req.get_uri_args()
local product_id = uri_args['product_id']
local cache_ngx = ngx.shared.dis_cache;
local adCache = cache_ngx:get('productcache'..product_id);
if adCache == "" or adCache == nil then
  local redis = require("resty.redis")     --引入redis
  local red = redis:new() red:set_timeout(2000)     --初始化 设置超时时间
  local ip ="192.168.29.108"
  local port = 6379
  red:connect(ip,port)
  red:auth("root")
  local rescontent=red:get("product_"..product_id)
  ngx.say(rescontent)
  red:close()
  cache_ngx:set('productcache'..product_id, rescontent, 10*60);
else
  ngx.say(adCache)
end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值