我們正在考慮將我們的php會話數據移至redis。將php會話移至redis。是否有可能不會丟失現有會話數據?
設置看起來很簡單。只需在php.ini中設置以下內容並重新啓動apache。它應該全部設置。:
session.save_handler = redis
session.save_path = "tcp://host1:6379"
如果可能我希望我們的用戶不要注意遷移。是否可以將會話數據移動到redis而不丟失任何現有的會話數據?
我們正在考慮將我們的php會話數據移至redis。將php會話移至redis。是否有可能不會丟失現有會話數據?
設置看起來很簡單。只需在php.ini中設置以下內容並重新啓動apache。它應該全部設置。:
session.save_handler = redis
session.save_path = "tcp://host1:6379"
如果可能我希望我們的用戶不要注意遷移。是否可以將會話數據移動到redis而不丟失任何現有的會話數據?
對於您所要求的問題,目前沒有現成的解決方案可用,但爲此任務編寫定製腳本實際上可以非常簡單。
Esentially,在redis的phpredis存儲會話數據作爲具有下面的項名稱格式字符串:PHPREDIS_SESSION:$sessionid
,其中$sessionid
是會話的PHP的ID,經由session_id()
的一個可檢索。會話數據被編碼爲php會話序列化變量(與普通的php序列化/反序列化略有不同,參見session_encode)。
現在我們知道這一點,有兩種可能遷移存儲在文件中的會話數據:
迭代通過每一個會話文件(實際路徑在php.ini中設置爲session.save_path
),閱讀數據並將其寫回redis。這些文件本身存儲會話數據的php會話序列化表示,這意味着內容可以直接複製到redis,文件名具有以下模式:sess_$sessionid
,其中$ sessionid是,你猜對了,id你會想用你的Redis鍵。
現在通過保持基於文件的會話來逐步遷移數據,但是在會話數據被使用時實時填充redis,直到存儲在redis中的會話數量看起來足以完成交換。這可以通過做這樣的事情來實現:每個腳本結束
$redis->set("PHPREDIS_SESSION:".session_id(), session_encode());
權利之前。此方法可能會增加一點開銷 ,具體取決於會話中的數據量以及session_encode 的工作方式。
可能的,是的,簡單,不是那麼多。
AFAIK,phpredis沒有移植腳本,所以你必須自己寫一個。你可能想看看Cm_RedisSession's script,它爲那個redis模塊做了類似的事情。
剛剛在bash中創建了這樣的腳本,並添加到我的回購。
如果您正在使用symfony中,你可以使用如下命令:
陽明配置:
parameters:
redis_address: "localhost"
project_name : "ACME_"
snc_redis:
clients:
default:
type: predis
alias: default
dsn: redis://%redis_address%
logging: '%kernel.debug%'
session:
type: predis
alias: session
dsn: redis://%redis_address%/1
logging: true
session:
client: session
prefix: '%project_name%PHPREDIS_SESSION'
ttl: 7776000 # 90 days
symfony的命令:
<?php
// Command: app/console acme:migrate:session:files:to:redis --env=dev
namespace Acme\AppBundle\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Finder\Finder;
class MigrateSessionFilesToRedisCommand extends ContainerAwareCommand {
protected $env;
protected function configure() {
$this->setName('acme:migrate:session:files:to:redis')
->setDescription("Migrate Session Files To Redis")
->setHelp("Migrate Session Files To Redis");
}
protected function execute(InputInterface $input, OutputInterface $output) {
$sessionPath = realpath(sprintf('%s%s', $this->getContainer()->getParameter('kernel.root_dir'), '/sessions'));
$prefix = 'ACME_PHPREDIS_SESSION';
$redis = $this->getContainer()->get('snc_redis.session');
$finder = new Finder();
$finder->files()->in($sessionPath);
foreach ($finder as $file) {
$realPath = $file->getRealpath();
$sessionId = str_replace('sess_', '', $file->getRelativePathname());
$redis->append(sprintf('%s:%s', $prefix, $sessionId) , file_get_contents($realPath));
}
}
}
注意:你項目ID /名稱替換「ACME」,並設置文件存儲的權利會話路徑。
可能的,是的,簡單,不是那麼多。 Afaik phpredis沒有遷移腳本,所以你必須自己寫一個。你可能想看看[Cm_RedisSession的腳本](https://github.com/colinmollenhour/Cm_RedisSession/blob/master/migrateSessions.php),它爲redis模塊做了類似的事情。 –
謝謝。我認爲你的評論回答了我的問題。我自己找不到這樣的腳本。查看腳本,需要使用的庫提供一些功能。在編寫遷移腳本之前,可能需要writeRawSession()纔是必需的。我已將此作爲一個問題提交給phpredis。如果您不介意,請將您的評論寫爲答案,以便我可以將其標記爲已接受。 – Haluk
其實一個自定義腳本應該很容易構建。基本上你會想遍歷每個會話文件,並在PHREDISISESSION下的redis中創建一個新的字符串:filename其中,filename是會話文件的名稱,這也恰好是會話ID,並將此密鑰設置爲文件1的內容:1。或者,您也可以在之後設置自定義到期時間。 – Mahn