1、redis 中的每一個(gè)數(shù)據(jù)庫(kù),都由一個(gè) redisDb 的結(jié)構(gòu)存儲(chǔ)。其中,redisDb.id 存儲(chǔ)著 redis 數(shù)據(jù)庫(kù)以整數(shù)表示的號(hào)碼。redisDb.dict 存儲(chǔ)著該庫(kù)所有的鍵值對(duì)數(shù)據(jù)。redisDb.expires 保存著每一個(gè)鍵的過(guò)期時(shí)間。
創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供安國(guó)網(wǎng)站建設(shè)、安國(guó)做網(wǎng)站、安國(guó)網(wǎng)站設(shè)計(jì)、安國(guó)網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、安國(guó)企業(yè)網(wǎng)站模板建站服務(wù),10余年安國(guó)做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
2、當(dāng)redis 服務(wù)器初始化時(shí),會(huì)預(yù)先分配 16 個(gè)數(shù)據(jù)庫(kù)(該數(shù)量可以通過(guò)配置文件配置),所有數(shù)據(jù)庫(kù)保存到結(jié)構(gòu) redisServer 的一個(gè)成員 redisServer.db 數(shù)組中。當(dāng)我們選擇數(shù)據(jù)庫(kù) select number 時(shí),程序直接通過(guò) redisServer.db[number] 來(lái)切換數(shù)據(jù)庫(kù)。有時(shí)候當(dāng)程序需要知道自己是在哪個(gè)數(shù)據(jù)庫(kù)時(shí),直接讀取 redisDb.id 即可。
3、既然我們知道一個(gè)數(shù)據(jù)庫(kù)的所有鍵值都存儲(chǔ)在redisDb.dict中,那么我們要知道如果找到key的位置,就有必要了解一下dict 的結(jié)構(gòu)了:
typedef struct dict {
// 特定于類型的處理函數(shù)
dictType *type;
// 類型處理函數(shù)的私有數(shù)據(jù)
void *privdata;
// 哈希表(2個(gè))
dictht ht[2];
// 記錄 rehash 進(jìn)度的標(biāo)志,值為-1 表示 rehash 未進(jìn)行
int rehashidx;
// 當(dāng)前正在運(yùn)作的安全迭代器數(shù)量
int iterators;
} dict;
由上述的結(jié)構(gòu)可以看出,redis 的字典使用哈希表作為其底層實(shí)現(xiàn)。dict 類型使用的兩個(gè)指向哈希表的指針,其中 0 號(hào)哈希表(ht[0])主要用于存儲(chǔ)數(shù)據(jù)庫(kù)的所有鍵值,而1號(hào)哈希表主要用于程序?qū)?0 號(hào)哈希表進(jìn)行 rehash 時(shí)使用,rehash 一般是在添加新值時(shí)會(huì)觸發(fā),這里不做過(guò)多的贅述。所以redis 中查找一個(gè)key,其實(shí)就是對(duì)進(jìn)行該dict 結(jié)構(gòu)中的 ht[0] 進(jìn)行查找操作。
4、既然是哈希,那么我們知道就會(huì)有哈希碰撞,那么當(dāng)多個(gè)鍵哈希之后為同一個(gè)值怎么辦呢?redis采取鏈表的方式來(lái)存儲(chǔ)多個(gè)哈希碰撞的鍵。也就是說(shuō),當(dāng)根據(jù)key的哈希值找到該列表后,如果列表的長(zhǎng)度大于1,那么我們需要遍歷該鏈表來(lái)找到我們所查找的key。當(dāng)然,一般情況下鏈表長(zhǎng)度都為是1,所以時(shí)間復(fù)雜度可看作o(1)。
二、當(dāng)redis 拿到一個(gè)key 時(shí),如果找到該key的位置。
了解了上述知識(shí)之后,我們就可以來(lái)分析redis如果在內(nèi)存找到一個(gè)key了。
1、當(dāng)拿到一個(gè)key后, redis 先判斷當(dāng)前庫(kù)的0號(hào)哈希表是否為空,即:if (dict-ht[0].size == 0)。如果為true直接返回NULL。
2、判斷該0號(hào)哈希表是否需要rehash,因?yàn)槿绻谶M(jìn)行rehash,那么兩個(gè)表中者有可能存儲(chǔ)該key。如果正在進(jìn)行rehash,將調(diào)用一次_dictRehashStep方法,_dictRehashStep 用于對(duì)數(shù)據(jù)庫(kù)字典、以及哈希鍵的字典進(jìn)行被動(dòng) rehash,這里不作贅述。
3、計(jì)算哈希表,根據(jù)當(dāng)前字典與key進(jìn)行哈希值的計(jì)算。
4、根據(jù)哈希值與當(dāng)前字典計(jì)算哈希表的索引值。
5、根據(jù)索引值在哈希表中取出鏈表,遍歷該鏈表找到key的位置。一般情況,該鏈表長(zhǎng)度為1。
6、當(dāng) ht[0] 查找完了之后,再進(jìn)行了次rehash判斷,如果未在rehashing,則直接結(jié)束,否則對(duì)ht[1]重復(fù)345步驟。
到此我們就找到了key在內(nèi)存中的位置了。
這篇文章主要介紹了php實(shí)現(xiàn)redis數(shù)據(jù)庫(kù)指定庫(kù)號(hào)遷移的方法,涉及對(duì)于redis數(shù)據(jù)庫(kù)的操作技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
本文實(shí)例講述了php實(shí)現(xiàn)redis數(shù)據(jù)庫(kù)指定庫(kù)號(hào)遷移的方法,分享給大家供大家參考。具體如下:
redis普通的數(shù)據(jù)庫(kù)遷移,只能整個(gè)redis
save,或者利用主從,當(dāng)然也可以安裝一個(gè)redis-dump,不過(guò)比較麻煩,這里提供一種php的腳本,實(shí)現(xiàn)指定庫(kù)號(hào)的遷移,其實(shí)也就是遍歷根據(jù)存儲(chǔ)類型,讀出來(lái),插入新庫(kù),效果是這樣:
代碼如下:
[root@localhost
~]#
php
1.php
1/407
101/407
201/407
301/407
401/407
PHP實(shí)例代碼如下:
代碼如下:
?php
$from
=
'10.0.2.52:6379/7';
$to
=
'127.0.0.1:6379/7';
$from_redis
=
redis_init($from);
$to_redis
=
redis_init($to);
$keys
=
$from_redis-keys('*');
$count
=
0;
$total
=
count($keys);
foreach($keys
as
$key){
if(++$count
%
100
==
1){
echo
"$count/$totaln";
}
$type
=
$from_redis-type($key);
switch($type){
case
Redis::REDIS_STRING:
$val
=
$from_redis-get($key);
$to_redis-set($key,
$val);
break;
case
Redis::REDIS_LIST:
$list
=
$from_redis-lRange($key,
0,
-1);
foreach($list
as
$val){
$to_redis-rPush($key,
$val);
}
break;
case
Redis::REDIS_HASH:
$hash
=
$from_redis-hGetAll($key);
$to_redis-hMSet($key,
$hash);
break;
case
Redis::REDIS_ZSET:
$zset
=
$from_redis-zRange($key,
0,
-1,
true);
foreach($zset
as
$val=$score){
$to_redis-zAdd($key,
$score,
$val);
}
break;
}
}
function
redis_init($conf){
$redis
=
new
Redis();
preg_match('/^([^:]+)(:[0-9]+)?/(.+)?/',
$conf,
$ms);
$host
=
$ms[1];
$port
=
trim($ms[2],
':');
$db
=
$ms[3];
$redis-connect($host,
$port);
$redis-select($db);
return
$redis;
}
?
希望本文所述對(duì)大家的php程序設(shè)計(jì)有所幫助。
1、創(chuàng)建userinfo_update.php,用于查詢用戶信息,先顯示信息,在修改:先通過(guò)GET獲取用戶編號(hào)查詢用戶信息:$sql = "select * from user_info where user_id='".$_GET['userId']."'"; $result = mysql_query($sql,$con);if($row = mysql_fetch_array($result)){}。
2、頁(yè)面效果。
3、創(chuàng)建update.php,用于修改用戶信息:使用到了mysql_affected_rows() 函數(shù)返回前一次 MySQL 操作所影響的記錄行數(shù)。//通過(guò)post獲取頁(yè)面提交數(shù)據(jù)信息$userId = $_POST[userId];
$userName = $_POST[userName];$userAge = $_POST[userAge];
4、$sql = "update user_info set user_name='".$userName."',user_age=".$userAge." where user_id='".$userId."'";mysql_query($sql,$conn);//執(zhí)行SQL$mark? = mysql_affected_rows();//返回影響行數(shù)$url = "userinf_select.php"; 。
5、運(yùn)行結(jié)果。
select 查詢的時(shí)候始終先查 redis 有沒(méi)有,沒(méi)有去查數(shù)據(jù)庫(kù),再把結(jié)果緩存起來(lái);
update 修改完數(shù)據(jù)庫(kù)內(nèi)容后,同時(shí)對(duì) redis 中緩存的數(shù)據(jù)做一下 update 更新操作,這樣 select 查詢 redis 的時(shí)候就是查詢的最新數(shù)據(jù);
同理,delete、insert 操作數(shù)據(jù)庫(kù)后也要同時(shí)對(duì) redis 中緩存的數(shù)據(jù)做 update 更新操作,這樣 select 查詢 redis 的時(shí)候就是查詢的最新數(shù)據(jù);
這樣,所有的查詢操作就都是對(duì) redis 做緩存讀取,可以緩解數(shù)據(jù)庫(kù)的壓力;