亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Redis如何使用LRU算法?

發布時間:2020-05-23 11:46:23 來源:億速云 閱讀:292 作者:鴿子 欄目:關系型數據庫

1、設置Redis使用LRU算法

LRU(Least Recently Used)最近最少使用算法是眾多置換算法中的一種。
Redis中有一個maxmemory概念,主要是為了將使用的內存限定在一個固定的大小。Redis用到的LRU 算法,是一種近似的LRU算法。

(1)設置maxmemory

上面已經說過maxmemory是為了限定Redis最大內存使用量。有多種方法設定它的大小。其中一種方法是通過CONFIG SET設定,如下:

127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "0"
127.0.0.1:6379> CONFIG SET maxmemory 100MB
OK
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "104857600"

另一種方法是修改配置文件redis.conf:

maxmemory 100mb

注意,在64bit系統下,maxmemory設置為0表示不限制Redis內存使用,在32bit系統下,maxmemory隱式不能超過3GB。
當Redis內存使用達到指定的限制時,就需要選擇一個置換的策略。

(2)置換策略

當Redis內存使用達到maxmemory時,需要選擇設置好的maxmemory-policy進行對老數據的置換。
下面是可以選擇的置換策略:

  • noeviction: 不進行置換,表示即使內存達到上限也不進行置換,所有能引起內存增加的命令都會返回error

  • allkeys-lru: 優先刪除掉最近最不經常使用的key,用以保存新數據

  • volatile-lru: 只從設置失效(expire set)的key中選擇最近最不經常使用的key進行刪除,用以保存新數據

  • allkeys-random: 隨機從all-keys中選擇一些key進行刪除,用以保存新數據

  • volatile-random: 只從設置失效(expire set)的key中,選擇一些key進行刪除,用以保存新數據

  • volatile-ttl: 只從設置失效(expire set)的key中,選出存活時間(TTL)最短的key進行刪除,用以保存新數據

需要注意的是:

(1)設置maxmemory-policy的方法和設置maxmemory方法類似,通過redis.conf或是通過CONFIG SET動態修改。

(2)如果沒有匹配到可以刪除的key,那么volatile-lru、volatile-random和volatile-ttl策略和noeviction替換策略一樣——不對任何key進行置換。

(3)選擇合適的置換策略是很重要的,這主要取決于你的應用的訪問模式,當然你也可以動態的修改置換策略,并通過用Redis命令——INFO去輸出cache的命中率情況,進而可以對置換策略進行調優。

一般來說,有這樣一些常用的經驗:

  • 在所有的key都是最近最經常使用,那么就需要選擇allkeys-lru進行置換最近最不經常使用的key,如果你不確定使用哪種策略,那么推薦使用allkeys-lru。

  • 如果所有的key的訪問概率都是差不多的,那么可以選用allkeys-random策略去置換數據。

  • 如果對數據有足夠的了解,能夠為key指定hint(通過expire/ttl指定),那么可以選擇volatile-ttl進行置換。

volatile-lru 和 volatile-random經常在一個Redis實例既做cache又做持久化的情況下用到,然而,更好的選擇使用兩個Redis實例來解決這個問題。

設置是失效時間expire會占用一些內存,而采用allkeys-lru就沒有必要設置失效時間,進而更有效的利用內存。

(3)置換策略是如何工作的

理解置換策略的執行方式是非常重要的,比如:

  1. 客戶端執行一條新命令,導致數據庫需要增加數據(比如set key value)

  2. Redis會檢查內存使用,如果內存使用超過maxmemory,就會按照置換策略刪除一些key

  3. 新的命令執行成功

我們持續的寫數據會導致內存達到或超出上限maxmemory,但是置換策略會將內存使用降低到上限以下。

如果一次需要使用很多的內存(比如一次寫入一個很大的set),那么,Redis的內存使用可能超出最大內存限制一段時間。

(4)近似LRU算法

Redis中的LRU不是嚴格意義上的LRU算法實現,是一種近似的LRU實現,主要是為了節約內存占用以及提升性能。Redis有這樣一個配置——maxmemory-samples,Redis的LRU是取出配置的數目的key,然后從中選擇一個最近最不經常使用的key進行置換,默認的5,如下:

maxmemory-samples 5

可以通過調整樣本數量來取得LRU置換算法的速度或是精確性方面的優勢。

Redis不采用真正的LRU實現的原因是為了節約內存使用。雖然不是真正的LRU實現,但是它們在應用上幾乎是等價的。下圖是Redis的近似LRU實現和理論LRU實現的對比:

Redis如何使用LRU算法?

測試開始首先在Redis中導入一定數目的key,然后從第一個key依次訪問到最后一個key,因此根據LRU算法第一個被訪問的key應該最新被置換,之后再增加50%數目的key,導致50%的老的key被替換出去。

在上圖中你可以看到三種類型的點,組成三種不同的區域:

  1. 淡灰色的是被置換出去的key

  2. 灰色的是沒有被置換出去的key

  3. 綠色的是新增加的key

理論LRU實現就像我們期待的那樣,最舊的50%數目的key被置換出去,Redis的LRU將一定比例的舊key置換出去。

可以看到在樣本數為5的情況下,Redis3.0要比Redis2.8做的好很多,Redis2.8中有很多應該被置換出去的數據沒有置換出去。在樣本數為10的情況下,Redis3.0很接近真正的LRU實現。

LRU是一個預測未來我們會訪問哪些數據的模型,如果我們訪問數據的形式接近我們預想——冪律,那么近似LRU算法實現將能處理的很好。

在模擬測試中我們可以發現,在冪律訪問模式下,理論LRU和Redis近似LRU的差距很小或者就不存在差距。

如果你將maxmemory-samples設置為10,那么Redis將會增加額外的CPU開銷以保證接近真正的LRU性能,可以通過檢查命中率來查看有什么不同。

通過CONFIG SET maxmemory-samples <count>動態調整樣本數大小,做一些測試驗證你的猜想。

2、LRU的實現

<?php
/**
 * LRU是最近最少使用頁面置換算法(Least Recently Used),也就是首先淘汰最長時間未被使用的頁面
 */
class LRU_Cache
{

    private $array_lru = array();
    private $max_size = 0;

    function __construct($size)
    {
        // 緩存最大存儲
        $this->max_size = $size;
    }

    public function set_value($key, $value)
    {
        // 如果存在,則向隊尾移動,先刪除,后追加
        // array_key_exists() 函數檢查某個數組中是否存在指定的鍵名,如果鍵名存在則返回true,如果鍵名不存在則返回false。
        if (array_key_exists($key, $this->array_lru)) {
            // unset() 銷毀指定的變量。
            unset($this->array_lru[$key]);
        }
        // 長度檢查,超長則刪除首元素
        if (count($this->array_lru) > $this->max_size) {
            // array_shift() 函數刪除數組中第一個元素,并返回被刪除元素的值。
            array_shift($this->array_lru);
        }
        // 隊尾追加元素
        $this->array_lru[$key] = $value;
    }

    public function get_value($key)
    {
        $ret_value = false;

        if (array_key_exists($key, $this->array_lru)) {
            $ret_value = $this->array_lru[$key];
            // 移動到隊尾
            unset($this->array_lru[$key]);
            $this->array_lru[$key] = $ret_value;
        }

        return $ret_value;
    }

    public function vardump_cache()
    {
        echo "<br>";
        var_dump($this->array_lru);
    }
}

$cache = new LRU_Cache(5);                          // 指定了最大空間 6
$cache->set_value("01", "01");
$cache->set_value("02", "02");
$cache->set_value("03", "03");
$cache->set_value("04", "04");
$cache->set_value("05", "05");
$cache->vardump_cache();
echo "<br>";

$cache->set_value("06", "06");
$cache->vardump_cache();
echo "<br>";

$cache->set_value("03", "03");
$cache->vardump_cache();
echo "<br>";

$cache->set_value("07", "07");
$cache->vardump_cache();
echo "<br>";

$cache->set_value("01", "01");
$cache->vardump_cache();
echo "<br>";

$cache->get_value("04");
$cache->vardump_cache();
echo "<br>";

$cache->get_value("05");
$cache->vardump_cache();
echo "<br>";

$cache->get_value("10");
$cache->vardump_cache();
echo "<br>";

以上就是redis中設置lru算法的方法的詳細內容,更多請關注億速云其它相關文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

始兴县| 平山县| 慈溪市| 彭州市| 安国市| 景宁| 恭城| 南开区| 东乌珠穆沁旗| 砀山县| 阜平县| 奉节县| 全南县| 霍山县| 渝中区| 呼和浩特市| 莎车县| 界首市| 始兴县| 正安县| 玛多县| 凉山| 西丰县| 桐乡市| 泰顺县| 开江县| 辽中县| 靖江市| 东山县| 吉林市| 鄯善县| 景宁| 庆云县| 板桥市| 卓资县| 班玛县| 莲花县| 阿瓦提县| 姚安县| 讷河市| 崇信县|