2012-09-29 56 views
1

我們正在考慮將我們的php會話數據移至redis。將php會話移至redis。是否有可能不會丟失現有會話數據?

設置看起來很簡單。只需在php.ini中設置以下內容並重新啓動apache。它應該全部設置。:

session.save_handler = redis 
session.save_path = "tcp://host1:6379" 

如果可能我希望我們的用戶不要注意遷移。是否可以將會話數據移動到redis而不丟失任何現有的會話數據?

+1

可能的,是的,簡單,不是那麼多。 Afaik phpredis沒有遷移腳本,所以你必須自己寫一個。你可能想看看[Cm_RedisSession的腳本](https://github.com/colinmollenhour/Cm_RedisSession/blob/master/migrateSessions.php),它爲redis模塊做了類似的事情。 –

+0

謝謝。我認爲你的評論回答了我的問題。我自己找不到這樣的腳本。查看腳本,需要使用的庫提供一些功能。在編寫遷移腳本之前,可能需要writeRawSession()纔是必需的。我已將此作爲一個問題提交給phpredis。如果您不介意,請將您的評論寫爲答案,以便我可以將其標記爲已接受。 – Haluk

+1

其實一個自定義腳本應該很容易構建。基本上你會想遍歷每個會話文件,並在PHREDISISESSION下的redis中創建一個新的字符串:filename其中,filename是會話文件的名稱,這也恰好是會話ID,並將此密鑰設置爲文件1的內容:1。或者,您也可以在之後設置自定義到期時間。 – Mahn

回答

4

對於您所要求的問題,目前沒有現成的解決方案可用,但爲此任務編寫定製腳本實際上可以非常簡單。

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 的工作方式。

2

可能的,是的,簡單,不是那麼多。

AFAIK,phpredis沒有移植腳本,所以你必須自己寫一個。你可能想看看Cm_RedisSession's script,它爲那個redis模塊做了類似的事情。

1

如果您正在使用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」,並設置文件存儲的權利會話路徑