<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                >[info] Redis分布式鎖 **為什么需要分布式鎖:** ![](https://img.kancloud.cn/ef/d3/efd362fff4781e6ff52589d2571d349b_937x477.png) **保證互斥:** ![](https://img.kancloud.cn/5a/22/5a22ba2813af30484a122adbc26a6967_479x382.png) **死鎖:** ![](https://img.kancloud.cn/80/e5/80e54f2332181a2da1fed8409dfe3a54_414x374.png) **加鎖:** ~~~php <?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); 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 <?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(); } } ?> ~~~ >[info] 內存淘汰策略 **定期刪除:** 指的是redis默認是每隔100ms就隨機抽取一些設置了過期時間的key,檢查其是否過期,如果過期就刪除。 **惰性刪除:** 獲取某個key的時候,redis會檢查一下 ,這個key如果設置了過期時間那么是否過期了?如果過期了此時就會刪除,不會給你返回任何東西。 **其他淘汰策略:** ~~~ volatile-random:從已設置過期時間的數據集中任意選擇數據淘汰。 allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰 volatile-lru:從已設置過期時間的數據集中挑選最近最少使用的數據淘汰。 allkeys-lru:從數據集中挑選最近最少使用的數據淘汰 volatile-ttl:從已設置過期時間的數據集中挑選將要過期的數據淘汰。 no-enviction(驅逐):禁止驅逐數據,這也是默認策略 ~~~ **lru淘汰策略:** 根據冷熱數據排序,最熱數據排在最上面,反之冷數據反正最底端。 ***** 按照英文的直接原義就是Least Recently Used,最近最久未使用法,它是按照一個非常著名的計算機操作系統基礎理論得來的:最近使用的頁面數據會在未來一段時期內仍然被使用,已經很久沒有使用的頁面很有可能在未來較長的一段時間內仍然不會被使用。基于這個思想,會存在一種緩存淘汰機制,每次從內存中找到最久未使用的數據然后置換出來,從而存入新的數據!它的主要衡量指標是使用的時間,附加指標是使用的次數。在計算機中大量使用了這個機制,它的合理性在于優先篩選熱點數據,所謂熱點數據,就是最近最多使用的數據!因為,利用LRU我們可以解決很多實際開發中的問題,并且很符合業務場景。 ![](https://img.kancloud.cn/c4/ba/c4ba020eaa2cabf7232676d01e80f0d7_760x648.png) ***** **使用php實現lru策略:** ~~~php <?php namespace App\Services; class LruService { /* * 頭部節點 */ private $head; /* * 尾部節點 */ private $tail; /* * 最大容量,大于淘汰部位節點指向上一個元素 */ private $capacity; /* * 存儲key對應的節點 */ private $hashmap; public function __construct($capacity) { $this->capacity = $capacity; $this->hashmap = array(); $this->head = new LruNodeService(null,null); $this->tail = new LruNodeService(null,null); $this->head->setNext($this->tail); $this->tail->setPrevious($this->head); } /** * 獲取元素 * @param $key * @return null */ public function get($key) { if (!isset($this->hashmap[$key])) { return null; } $node = $this->hashmap[$key]; if (count($this->hashmap) == 1) { return $node->getData(); } //先刪除已經存在的結點 $this->detach($node); //重新將新結點插入到頭結點之后 $this->attach($this->head, $node); return $node->getData(); } /** * 設置key value * @param $key * @param $data * @return bool */ public function put($key, $data) { if ($this->capacity <= 0) { return false; } if (isset($this->hashmap[$key]) && !empty($this->hashmap[$key])) { $node = $this->hashmap[$key]; //重置結點到頭結點之后 $this->detach($node); $this->attach($this->head, $node); $node->setData($data); } else { $node = new LruNodeService($key, $data); $this->hashmap[$key] = $node; //添加節點到頭部節點之后 $this->attach($this->head, $node); //檢測容量是否達到最大值 if (count($this->hashmap) > $this->capacity) { //如果達到最大值 刪除尾節點左指針指向的元素 $nodeToRemove = $this->tail->getPrevious(); $this->detach($nodeToRemove); unset($this->hashmap[$nodeToRemove->getKey()]); } } return true; } /** * 刪除key * @param $key * @return bool */ public function remove($key) { if (!isset($this->hashmap[$key])) { return false; } $nodeToRemove = $this->hashmap[$key]; $this->detach($nodeToRemove); unset($this->hashmap[$nodeToRemove->getKey()]); return true; } /** * 添加新結點到頭結點之后 * @param $head * @param $node */ private function attach($head, $node) { //雙向鏈表插入一個元素到頭結點之后 $node->setPrevious($head); $node->setNext($head->getNext()); $node->getNext()->setPrevious($node); $node->getPrevious()->setNext($node); } /** * 刪除結點 * @param $node */ private function detach($node) { $node->getPrevious()->setNext($node->getNext()); $node->getNext()->setPrevious($node->getPrevious()); } } ?> ~~~ ~~~php <?php namespace App\Services; class LruNodeService { private $key; //key對應的內容 private $data; //結點右指針 private $next; //結點左指針 private $previous; /** * Node constructor. * @param $key * @param $data */ public function __construct($key, $data) { $this->key = $key; $this->data = $data; } /** * Sets a new value for the node data * @param string the new content of the node */ public function setData($data) { $this->data = $data; } /** * Sets a node as the next node * @param Node $next the next node */ public function setNext($next) { $this->next = $next; } /** * Sets a node as the previous node * @param Node $previous the previous node */ public function setPrevious($previous) { $this->previous = $previous; } /** * Returns the node key * @return string the key of the node */ public function getKey() { return $this->key; } /** * Returns the node data * @return mixed the content of the node */ public function getData() { return $this->data; } /** * Returns the next node * @return Node the next node of the node */ public function getNext() { return $this->next; } /** * Returns the previous node * @return Node the previous node of the node */ public function getPrevious() { return $this->previous; } } ?> ~~~ >[info] 多級緩存 1. 提速 2. 減少服務器壓力 3. 提高系統并發 ***** **Openresty安裝:** OpenResty由中國 人章亦春發起,提供了很多高質量的第三方模塊。OpenResty 是一個強大的 Web 應用服務器,OpenResty可以快速構造出 足以勝任10K 乃至1000K以上并發連接響應的超高性能 Web 應用系統。 360,UPYUN,阿里云,新浪,騰訊網,去哪兒網,酷狗音樂等都是 OpenResty 的深度 用戶。 1. 安裝依賴 ~~~ yum install readline-devel pcre-devel openssl-devel ~~~ 2. 獲取安裝包解壓 ~~~ wget https://openresty.org/download/ngx_openresty-1.9.7.1.tar.gz # 下載 tar xzvf ngx_openresty-1.9.7.1.tar.gz # 解壓 ~~~ 3. 進入安裝目錄,編譯安裝 ~~~ cd ngx_openresty-1.9.7.1/ ./configure make ~~~ ***** **使用Openresty-創建lua腳本:** 1. 存 redis ~~~ 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}") ~~~ 2. 存本地 ~~~ 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 ~~~ 3. 配置 nginx >[info] Redis - Key 的設計 1. 內存 2. 可讀性 **主鍵存儲查詢:** 1. 表作為key的前綴 2. 列名作為key名 3. 主鍵值保證數據唯一 4. 數據列名 **例如:** user:username:uid:1 starsky product:uid:store 1 ***** **非主鍵存儲查詢:** 可以先根據列名設置一個key-value的值,然后在根據查詢到的value去查詢具體的數據,例如: Set user:username:starsky:uid 1 $uid = Get user:username:starsky:uid $user = get user: $uid:userinfo
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看