當前位置:首頁 » 存儲配置 » redis存儲位置

redis存儲位置

發布時間: 2022-06-10 19:57:48

① redis怎麼存儲

  1. redis是一個性能非常優秀的內存資料庫,通過key-value存儲系統。

  2. 和Memcached類似,它支持存儲的value類型相對更多,包括string(字元串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hashs(哈希類型)。

  3. 這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。

  4. 與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁碟或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。

② redis 所有key 都在內存么

Redis 中的每一個資料庫,都由一個 redisDb 的結構存儲。
其中,redisDb.id 存儲著 redis 資料庫以整數表示的號碼。
redisDb.dict 存儲著該庫所有的鍵值對數據。redisDb.expires 保存著每一個鍵的過期時間。

③ 怎麼樣使用Redis來存儲和查詢ip數據

今天朋友打了個電話,他們網站的業務要根據客戶的ip地址快速定位客戶的地理位置。網上已經有一大堆類似的ip地址庫可以用,但問題是這些地址庫的數據表結構大多如下所示
+--------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+----------------+
| ip_id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| ip_country | varchar(50) | NO | | NULL | |
| ip_startip | bigint(11) | NO | MUL | NULL | |
| ip_endip | bigint(11) | NO | MUL | NULL | |
| country_code | varchar(2) | NO | | NULL | |
| zone_id | int(11) | NO | | 0 | |
+--------------+------------------+------+-----+---------+----------------+

最核心的部分是三個: ip_startip , ip_endip 以及 ip_id 。其中 ip_id 是要查詢的結果,當然也可以把 zone_id 和 ip_country 包括進去。這里就用 ip_id 來特指查詢結果了。
面對這個表,沒什麼其它辦法,查詢語句只能是
SELECT * FROM who_ip WHERE ip_startip <= {ip} AND ip_endip >= {ip}

其中 {ip} 是要查詢的ip地址,為了方便查詢,在php中一般要用 ip2long函數把它轉換為一個整數。現在問題來了,這個表有400萬條數據,無論你怎麼優化它的索引結構(實際上我覺得這沒啥用),在以上查詢語句中都要耗費2秒以上的時間,對於一個高頻使用的介面,這顯然是不可忍受的。
REDIS能不能解決這個問題。實際上這也是朋友最關心的問題,因為知道Redis有強大數據結構和超快的速度,那麼能不能設計出適應這種查詢場景的結構。
范圍查詢,首先想到的就是Redis裡面的 Sorted Sets 結構,這也是redis中唯一可以指定范圍( SCORE 值)查詢的結構了,所以基本上希望都寄託在它身上了。
最簡單粗暴的方法就是把 ip_startip 和 ip_endip 都轉化為 Sorted Sets 里的 Score ,然後把 ip_id 定義為 Member 。這樣我們的查詢就很簡單了,只需要用 ZRANGESCORE 查詢出離ip最近SCORE對應的兩個 ip_id 即可。然後再分析,如果這兩個 ip_id 是相同的,那麼說明這個ip在這個地址段,如果不同的話證明這個ip地址沒有被任何地址段所定義,是一個未知的ip。
基本邏輯是沒有問題的,但是最大的問題還是性能上的挑戰。根據我的經驗,一個SET 裡面放10萬條數據以上就已經很慢了,如果放到400萬這種量級,我非常懷疑它跟mysql相比還有優勢嗎?
我設計的存儲結構
我的解決方案是把這個地址庫切分,每一片區最多保存65536個地址。也就是說如果一個ip地址段為 188.88.77.22 - 188.90.78.10 ,那麼我們就把它切分為
188.88.77.22 - 188.88.77.255
188.89.0.0 - 188.89.255.255
188.90.0.0 - 189.90.78.10

也就是我們保證每一個ip地址段都被保存在 xxx.xxx.0.0 - xxx.xxx.255.255的一個區段中,這個區段的理論極限是保存65536個值,實際上要遠小於這個數字。而這樣的區段理論上也有65536個,這都是ip地址的設計所限,當然實際上也遠小於這個值。
因此這樣的設計基本上就能滿足我們的性能需要了。以下是我用php寫的數據切分程序
<?php

// redis 參數
define('REDIS_HOST', '127.0.0.1');
define('REDIS_PORT', 6379);
define('REDIS_DB', 10);

define('MYSQL_HOST', 'localhost');
define('MYSQL_PORT', 3306);
define('MYSQL_USER', 'root');
define('MYSQL_PASS', '123456');
define('MYSQL_DB', 'who_brand');

define('MYSQL_TABLE', 'who_ip');
define('MYSQL_COLUMN_START', 'ip_startip');
define('MYSQL_COLUMN_END', 'ip_endip');
define('MYSQL_COLUMN_ID', 'ip_id');
define('MYSQL_PAGESIZE', 1000);

mysql_connect(MYSQL_HOST . ':' . MYSQL_PORT, MYSQL_USER, MYSQL_PASS);
mysql_select_db(MYSQL_DB);

function add_ip($page, $offset, $value) {
static $redis;

if (!$redis) {
$redis = new Redis();
$redis->connect(REDIS_HOST, REDIS_PORT);
$redis->select(REDIS_DB);
}

$key = 'ip:' . $page;
$redis->zAdd($key, $offset, $value);
}

$page = 0;
do {
$offset = $page * MYSQL_PAGESIZE;
$count = 0;

$res = mysql_query('SELECT * FROM ' . MYSQL_TABLE . ' LIMIT ' . MYSQL_PAGESIZE . " OFFSET {$offset}");

while ($ip = mysql_fetch_assoc($res)) {
$start = $ip[MYSQL_COLUMN_START];
$end = $ip[MYSQL_COLUMN_END];
$value = $ip[MYSQL_COLUMN_ID];

$startOffset = $start % 65536;
$endOffset = $end % 65536;

$start -= $startOffset;
$end -= $endOffset;

$startPage = $start / 65536;
$endPage = $end / 65536;

for ($i = $startPage; $i <= $endPage; $i ++) {
if ($i == $startPage) {
add_ip($i, $startOffset, 's:' . $value);

if ($i != $endPage) {
add_ip($i, 65535, 'e:' . $value);
}
}

if ($i == $endPage) {
add_ip($i, $endOffset, 'e:' . $value);

if ($i != $startPage) {
add_ip($i, 0, 's:' . $value);
}
}

if ($i != $endPage && $i != $startPage) {
add_ip($i, 0, 's:' . $value);
add_ip($i, 65535, 'e:' . $value);
}
}

echo ($page * MYSQL_PAGESIZE + $count) . "\n";
$count ++;
}

$page ++;
} while ($count = MYSQL_PAGESIZE);

<?php

define('REDIS_HOST', '127.0.0.1');
define('REDIS_PORT', 6379);
define('REDIS_DB', 10);

$redis = new Redis();
$redis->connect(REDIS_HOST, REDIS_PORT);
$redis->select(REDIS_DB);

$ip = ip2long('173.255.218.70');
$offset = $ip % 65536;
$page = ($ip - $offset) / 65536;

// 取出小於等於它的最接近值
$start = $redis->zRevRangeByScore('ip:' . $page, 0, $offset, array(
'limit' => array(0, 1)
));

// 取出大於等於它的最接近值
$end = $redis->zRangeByScore('ip:' . $page, $offset, 65535, array(
'limit' => array(0, 1)
));

if (empty($start) || empty($end)) {
echo 'unknown';
exit;
}

$start = $start[0];
$end = $end[0];

list ($startOp, $startId) = explode(':', $start);
list ($endOp, $endId) = explode(':', $end);

if ($startId != $endId) {
echo 'unknown';
exit;
}

echo $startId;

④ Redis存儲格式

redis目前提供四種數據類型:string,list,set及zset(sorted set)。
redis使用了兩種文件格式:全量數據和增量請求。全量數據格式是把內存中的數據寫入磁碟,便於下次讀取文件進行載入;增量請求文件則是把內存中的數據序列化為操作請求,用於讀取文件進行replay得到數據,序列化的操作包括SET、RPUSH、SADD、ZADD。redis的存儲分為內存存儲、磁碟存儲和log文件三部分,配置文件中有三個參數對其進行配置。save seconds updates,save配置,指出在多長時間內,有多少次更新操作,就將數據同步到數據文件。這個可以多個條件配合,比如默認配置文件中的設置,就設置了三個條件。appendonly yes/no ,appendonly配置,指出是否在每次更新操作後進行日誌記錄,如果不開啟,可能會在斷電時導致一段時間內的數據丟失。因為redis本身同步數據文件是按上面的save條件來同步的,所以有的數據會在一段時間內只存在於內存中。appendfsync no/always/everysec ,appendfsync配置,no表示等操作系統進行數據緩存同步到磁碟,always表示每次更新操作後手動調用fsync()將數據寫到磁碟,everysec表示每秒同步一次。

⑤ 如何查詢redis的緩存文件路徑

1、首先找到redis的安裝目錄,如下圖測試環境目錄,進入到/opt/install/redis-2.8.19/src,如下圖所示。

⑥ redis的數據是存在內存里嗎

Redis就是基於內存可持久化的key-value資料庫。

1、性能問題,Hashmap存儲大量數知據時需要不斷擴容,Redis支持2的32次方個key,每個key或者value大小最大512M。

2、Hashmap是線程不安道全的,redis因為操作原子性不需要考慮這個。

3、Redis可持久化,Hashmap雖然也可以序列專化,但是Java的序列化因為安全問題說是要廢除了,效率也沒有Redis高,而且Redis有多屬種持久化策略。

4、Redis可擴展可分布式部署。

(6)redis存儲位置擴展閱讀:

redis的存儲分為內存存儲、磁碟存儲和log文件三部分,配置文件中有三個參數對其進行配置。

save seconds updates,save配置,指出在多長時間內,有多少次更新操作,就將數據同步到數據文件。這個可以多個條件配合,比如默認配置文件中的設置,就設置了三個條件。

appendonly yes/no ,appendonly配置,指出是否在每次更新操作後進行日誌記錄,如果不開啟,可能會在斷電時導致一段時間內的數據丟失。因為redis本身同步數據文件是按上面的save條件來同步的,所以有的數據會在一段時間內只存在於內存中。

⑦ redis多個資料庫 內存怎麼分配的

1、redis 中的每一個資料庫,都由一個 redisDb 的結構存儲。其中,redisDb.id 存儲著 redis 資料庫以整數表示的號碼。redisDb.dict 存儲著該庫所有的鍵值對數據。redisDb.expires 保存著每一個鍵的過期時間。

2、當redis 伺服器初始化時,會預先分配 16 個資料庫(該數量可以通過配置文件配置),所有資料庫保存到結構 redisServer 的一個成員 redisServer.db 數組中。當我們選擇資料庫 select number 時,程序直接通過 redisServer.db[number] 來切換資料庫。有時候當程序需要知道自己是在哪個資料庫時,直接讀取 redisDb.id 即可。

3、既然我們知道一個資料庫的所有鍵值都存儲在redisDb.dict中,那麼我們要知道如果找到key的位置,就有必要了解一下dict 的結構了:

typedef struct dict {

// 特定於類型的處理函數
dictType *type;

// 類型處理函數的私有數據
void *privdata;

// 哈希表(2個)
dictht ht[2];

// 記錄 rehash 進度的標志,值為-1 表示 rehash 未進行
int rehashidx;

// 當前正在運作的安全迭代器數量
int iterators;
} dict;
由上述的結構可以看出,redis 的字典使用哈希表作為其底層實現。dict 類型使用的兩個指向哈希表的指針,其中 0 號哈希表(ht[0])主要用於存儲資料庫的所有鍵值,而1號哈希表主要用於程序對 0 號哈希表進行 rehash 時使用,rehash 一般是在添加新值時會觸發,這里不做過多的贅述。所以redis 中查找一個key,其實就是對進行該dict 結構中的 ht[0] 進行查找操作。

4、既然是哈希,那麼我們知道就會有哈希碰撞,那麼當多個鍵哈希之後為同一個值怎麼辦呢?redis採取鏈表的方式來存儲多個哈希碰撞的鍵。也就是說,當根據key的哈希值找到該列表後,如果列表的長度大於1,那麼我們需要遍歷該鏈表來找到我們所查找的key。當然,一般情況下鏈表長度都為是1,所以時間復雜度可看作o(1)。

二、當redis 拿到一個key 時,如果找到該key的位置。

了解了上述知識之後,我們就可以來分析redis如果在內存找到一個key了。

1、當拿到一個key後, redis 先判斷當前庫的0號哈希表是否為空,即:if (dict->ht[0].size == 0)。如果為true直接返回NULL。

2、判斷該0號哈希表是否需要rehash,因為如果在進行rehash,那麼兩個表中者有可能存儲該key。如果正在進行rehash,將調用一次_dictRehashStep方法,_dictRehashStep 用於對資料庫字典、以及哈希鍵的字典進行被動 rehash,這里不作贅述。

3、計算哈希表,根據當前字典與key進行哈希值的計算。

4、根據哈希值與當前字典計算哈希表的索引值。

5、根據索引值在哈希表中取出鏈表,遍歷該鏈表找到key的位置。一般情況,該鏈表長度為1。

6、當 ht[0] 查找完了之後,再進行了次rehash判斷,如果未在rehashing,則直接結束,否則對ht[1]重復345步驟。

到此我們就找到了key在內存中的位置了。

⑧ redis存儲幾個g的數據

首先看到 Redis 官方的說法是:『A String value can be at max 512 Megabytes in length.』。過大的 key 和 value 有兩個問題:Redis 是一個內存資料庫,如果容量過大的 key 和 value 首先會導致伺服器中的內存碎片。這會影響 Redis 的內存分配的效率,進一步導致內存的使用率下降。容量過大的 key 和 value 還有這樣幾個影響:a. 這些過大的數據需要更多的時間去傳輸數據b. 過大的數據傳輸可能會導致其他的請求超時如果 A 的響應數據過大,它可能會吃掉其他請求的超時時間。如下圖例子,如果 A 的響應數據過大,它會吃掉其他請求的超時時間

⑨ 什麼是Redis

redis 就是一個資料庫,不過與傳統資料庫不同的是 redis 的數據是存在內存和部分文件中的,所以讀寫速度非常快,因此 redis 被廣泛應用於緩存方向。另外,redis 也經常用來做分布式鎖。redis 提供了多種數據類型來支持不同的業務場景。除此之外,redis 支持事務 、持久化、LUA腳本、LRU驅動事件、多種集群方案。

⑩ Redis是將數據儲存進內存嗎

Redis就是基於內存可持久化的key-value資料庫。

  1. 性能問題,Hashmap存儲大量數據時需要不斷擴容,Redis支持2的32次方個key,每個key或者value大小最大512M;

  2. Hashmap是線程不安全的,redis因為操作原子性不需要考慮這個;

  3. Redis可持久化,Hashmap雖然也可以序列化,但是Java的序列化因為安全問題說是要廢除了,效率也沒有Redis高,而且Redis有多種持久化策略;

  4. Redis可擴展可分布式部署

熱點內容
99壓縮 發布:2025-01-11 08:43:47 瀏覽:831
ftp伺服器怎麼上傳 發布:2025-01-11 08:43:45 瀏覽:518
閱讀腳本是什麼 發布:2025-01-11 08:39:27 瀏覽:777
booljava 發布:2025-01-11 08:36:08 瀏覽:768
我的世界伺服器必要弄的東西 發布:2025-01-11 08:32:56 瀏覽:424
postgre資料庫 發布:2025-01-11 08:32:22 瀏覽:481
android登錄源碼 發布:2025-01-11 08:32:10 瀏覽:675
壓縮機閉閥 發布:2025-01-11 08:27:19 瀏覽:671
dns伺服器地址陝西 發布:2025-01-11 08:24:59 瀏覽:45
學思維編程 發布:2025-01-11 08:24:59 瀏覽:609