目次
session放入缓存(redis)、DB,sessionredis
为什么要把SESSION保存在缓存
SESSION保存在缓存中
ホームページ php教程 php手册 session放入缓存(redis)、DB,sessionredis

session放入缓存(redis)、DB,sessionredis

Jun 13, 2016 am 09:16 AM
redis

session放入缓存(redis)、DB,sessionredis

为什么要把SESSION保存在缓存

  就php来说,语言本身支持的session是以文件的方式保存到磁盘文件中,保存在指定的文件夹中,保存的路径可以在配置文件中设置或者在程序中使用函数session_save_path()进行设置,但是这么做有弊端,

<p>第一就是保存到文件系统中,效率低,只要有用到session就会从好多个文件中查找指定的sessionid,效率很低。</p>
<p>第二就是当用到多台服务器的时候可能会出现,session丢失问题(其实是保存在了其他服务器上)。</p>
ログイン後にコピー

  当然了,保存在缓存中可以解决上面的问题,如果使用php本身的session函数,可以使用session_set_save_handler()函数很方便的对session的处理过程进行重新控制。如果不用php的session系列函数,可以自己编写个类似的session函数,也是可以的,我现在做的这个项目就是这样,会根据用户的mid、登录时间进行求hash作为sessionId,每次请求的时候都必须加上sessionId才算合法(第一次登录的时候是不需要的,这个时候会创建sessionId,返回给客户端),这么做也很方便、简洁高效的。当然了,我这篇文章主要说的是在php自身的SESSION中”做做手脚”。

SESSION保存在缓存中

  php将缓存保存到redis中,可以使用配置文件,对session的处理和保存做修改,当然了,在程序中使用ini_set()函数去修改也可以,这个很方便测试,我这里就使用这种方式,当然了,要是生产环境还是建议使用配置文件。

<?<span>php
</span><span>ini_set</span>("session.save_handler", "redis"<span>);
</span><span>ini_set</span>("session.save_path", "tcp://localhost:6379"<span>);
</span><span>session_start</span><span>();
</span><span>header</span>("Content-type:text/html;charset=utf-8"<span>);
</span><span>if</span>(<span>isset</span>(<span>$_SESSION</span>['view'<span>])){
    </span><span>$_SESSION</span>['view'] = <span>$_SESSION</span>['view'] + 1<span>;
}</span><span>else</span><span>{
    </span><span>$_SESSION</span>['view'] = 1<span>;
}
</span><span>echo</span> "【view】{<span>$_SESSION</span>['view']}";
ログイン後にコピー

  这里设置session.save_handler方式为redis,session.save_path为redis的地址和端口,设置之后刷新,再回头查看redis,会发现redis中的生成了sessionId,sessionId和浏览器请求的是一样的,

open(string $savePath, string $sessionName); //open类似于构造函数,开始会话的时候会调用,比如使用session_start()函数之后

close(); //类似于类的析构函数,在write函数调用之后调用,session_write_close()之后之后也会执行

read(string $sessionId); //读取session的时候调用

write(string $sessionId, string $data); //保存数据的时候调用

destory($sessionId); //销毁会话的时候(session_destory()或者session_regenerate_id())会调用

gc($lifeTime); //垃圾清理函数,清理掉过期作废的数据

  主要就是实现这几个方法,根据不同的存储驱动可以自己设置不同的具体方法,我实现了mysql数据库和redis这两种保存session的驱动,如果有需要的话可以自己去扩展,扩展很方便很容易。

  下面是我的redis的实现(db和redis差不多,redis代码少,贴出来):

  我使用了接口的方式,这样扩展起来更方便,那天想用memcached了,直接添加就行了

<?<span>php
</span><span>include_once</span> __DIR__."/interfaceSession.php"<span>;
</span><span>/*</span><span>*
 * 以db的方式存储session
 </span><span>*/</span>
<span>class</span> redisSession <span>implements</span><span> interfaceSession{
    </span><span>/*</span><span>*
     * 保存session的数据库表的信息
     </span><span>*/</span>
    <span>private</span> <span>$_options</span> = <span>array</span><span>(
        </span>'handler' => <span>null</span>, <span>//</span><span>数据库连接句柄</span>
        'host' => <span>null</span>,
        'port' => <span>null</span>,
        'lifeTime' => <span>null</span>,<span>
    );

    </span><span>/*</span><span>*
     * 构造函数
     * @param $options 设置信息数组
     </span><span>*/</span>
    <span>public</span> <span>function</span> __construct(<span>$options</span>=<span>array</span><span>()){
        </span><span>if</span>(!<span>class_exists</span>("redis", <span>false</span><span>)){
            </span><span>die</span>("必须安装redis扩展"<span>);
        }
        </span><span>if</span>(!<span>isset</span>(<span>$options</span>['lifeTime']) || <span>$options</span>['lifeTime'] <= 0<span>){
            </span><span>$options</span>['lifeTime'] = <span>ini_get</span>('session.gc_maxlifetime'<span>);
        }
        </span><span>$this</span>->_options = <span>array_merge</span>(<span>$this</span>->_options, <span>$options</span><span>);
    }

    </span><span>/*</span><span>*
     * 开始使用该驱动的session
     </span><span>*/</span>
    <span>public</span> <span>function</span><span> begin(){
        </span><span>if</span>(<span>$this</span>->_options['host'] === <span>null</span> ||
           <span>$this</span>->_options['port'] === <span>null</span> ||
           <span>$this</span>->_options['lifeTime'] === <span>null</span><span>
        ){
            </span><span>return</span> <span>false</span><span>;
        }
        </span><span>//</span><span>设置session处理函数</span>
        <span>session_set_save_handler</span><span>(
            </span><span>array</span>(<span>$this</span>, 'open'),
            <span>array</span>(<span>$this</span>, 'close'),
            <span>array</span>(<span>$this</span>, 'read'),
            <span>array</span>(<span>$this</span>, 'write'),
            <span>array</span>(<span>$this</span>, 'destory'),
            <span>array</span>(<span>$this</span>, 'gc'<span>)
        );
    }
    </span><span>/*</span><span>*
     * 自动开始回话或者session_start()开始回话后第一个调用的函数
     * 类似于构造函数的作用
     * @param $savePath 默认的保存路径
     * @param $sessionName 默认的参数名,PHPSESSID
     </span><span>*/</span>
    <span>public</span> <span>function</span> open(<span>$savePath</span>, <span>$sessionName</span><span>){
        </span><span>if</span>(<span>is_resource</span>(<span>$this</span>->_options['handler'])) <span>return</span> <span>true</span><span>;
        </span><span>//</span><span>连接redis</span>
        <span>$redisHandle</span> = <span>new</span><span> Redis();
        </span><span>$redisHandle</span>->connect(<span>$this</span>->_options['host'], <span>$this</span>->_options['port'<span>]);
        </span><span>if</span>(!<span>$redisHandle</span><span>){
            </span><span>return</span> <span>false</span><span>;
        }

        </span><span>$this</span>->_options['handler'] = <span>$redisHandle</span><span>;
        </span><span>$this</span>->gc(<span>null</span><span>);
        </span><span>return</span> <span>true</span><span>;

    }

    </span><span>/*</span><span>*
     * 类似于析构函数,在write之后调用或者session_write_close()函数之后调用
     </span><span>*/</span>
    <span>public</span> <span>function</span><span> close(){
        </span><span>return</span> <span>$this</span>->_options['handler']-><span>close();
    }

    </span><span>/*</span><span>*
     * 读取session信息
     * @param $sessionId 通过该Id唯一确定对应的session数据
     * @return session信息/空串
     </span><span>*/</span>
    <span>public</span> <span>function</span> read(<span>$sessionId</span><span>){
        </span><span>return</span> <span>$this</span>->_options['handler']->get(<span>$sessionId</span><span>);
    }

    </span><span>/*</span><span>*
     * 写入或者修改session数据
     * @param $sessionId 要写入数据的session对应的id
     * @param $sessionData 要写入的数据,已经序列化过了
     </span><span>*/</span>
    <span>public</span> <span>function</span> write(<span>$sessionId</span>, <span>$sessionData</span><span>){
        </span><span>return</span> <span>$this</span>->_options['handler']->setex(<span>$sessionId</span>, <span>$this</span>->_options['lifeTime'], <span>$sessionData</span><span>);
    }

    </span><span>/*</span><span>*
     * 主动销毁session会话
     * @param $sessionId 要销毁的会话的唯一id
     </span><span>*/</span>
    <span>public</span> <span>function</span> destory(<span>$sessionId</span><span>){
        </span><span>return</span> <span>$this</span>->_options['handler']->delete(<span>$sessionId</span>) >= 1 ? <span>true</span> : <span>false</span><span>;
    }

    </span><span>/*</span><span>*
     * 清理绘画中的过期数据
     * @param 有效期
     </span><span>*/</span>
    <span>public</span> <span>function</span> gc(<span>$lifeTime</span><span>){
        </span><span>//</span><span>获取所有sessionid,让过期的释放掉</span>
        <span>$this</span>->_options['handler']->keys("*"<span>);
        </span><span>return</span> <span>true</span><span>;
    }

}</span>
ログイン後にコピー

  看看简单工厂模式

<span>class</span><span> session {
    </span><span>/*</span><span>*
     * 驱动程序句柄保存
     </span><span>*/</span>
    <span>private</span> <span>static</span> <span>$_handler</span> = <span>null</span><span>;

    </span><span>/*</span><span>*
     * 创建session驱动程序
     </span><span>*/</span>
    <span>public</span> <span>static</span> <span>function</span> getSession(<span>$type</span>, <span>$options</span><span>){
        </span><span>//</span><span>单例</span>
        <span>if</span>(<span>isset</span>(<span>$handler</span><span>)){
            </span><span>return</span> self::<span>$_handler</span><span>;
        }

        </span><span>switch</span> (<span>$type</span><span>) {
            </span><span>case</span> 'db': <span>//</span><span>数据库驱动session类型</span>
                    <span>include_once</span> __DIR__."/driver/dbSession.php"<span>;
                    </span><span>$handler</span> = <span>new</span> dbSession(<span>$options</span><span>);
                </span><span>break</span><span>;
            
            </span><span>case</span> 'redis': <span>//</span><span>redis驱动session类型</span>
                    <span>include_once</span> __DIR__."/driver/redisSession.php"<span>;
                    </span><span>$handler</span> = <span>new</span> redisSession(<span>$options</span><span>);
                </span><span>break</span><span>;
            </span><span>default</span>:
                    <span>return</span> <span>false</span><span>;
                </span><span>break</span><span>;
        }

        </span><span>return</span> self::<span>$_handler</span> = <span>$handler</span><span>;
    }
}</span>
ログイン後にコピー

  调用也很简单,

session::getSession('redis',<span>array</span><span>(
        </span>'host' => "localhost",
        'port' => "6379",<span>
    ))</span>-><span>begin();

</span><span>session_start</span>();
ログイン後にコピー

  数据库版本的也一样很简单就可以配置,需要的话可以在这里下载完整版和demo

 

 

  本文版权归作者iforever(luluyrt@163.com)所有,未经作者本人同意禁止任何形式的转载,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Redisクラスターモードの構築方法 Redisクラスターモードの構築方法 Apr 10, 2025 pm 10:15 PM

Redisクラスターモードは、シャードを介してRedisインスタンスを複数のサーバーに展開し、スケーラビリティと可用性を向上させます。構造の手順は次のとおりです。異なるポートで奇妙なRedisインスタンスを作成します。 3つのセンチネルインスタンスを作成し、Redisインスタンスを監視し、フェールオーバーを監視します。 Sentinel構成ファイルを構成し、Redisインスタンス情報とフェールオーバー設定の監視を追加します。 Redisインスタンス構成ファイルを構成し、クラスターモードを有効にし、クラスター情報ファイルパスを指定します。各Redisインスタンスの情報を含むnodes.confファイルを作成します。クラスターを起動し、CREATEコマンドを実行してクラスターを作成し、レプリカの数を指定します。クラスターにログインしてクラスター情報コマンドを実行して、クラスターステータスを確認します。作る

基礎となるRedisを実装する方法 基礎となるRedisを実装する方法 Apr 10, 2025 pm 07:21 PM

Redisはハッシュテーブルを使用してデータを保存し、文字列、リスト、ハッシュテーブル、コレクション、注文コレクションなどのデータ構造をサポートします。 Redisは、スナップショット(RDB)を介してデータを維持し、書き込み専用(AOF)メカニズムを追加します。 Redisは、マスタースレーブレプリケーションを使用して、データの可用性を向上させます。 Redisは、シングルスレッドイベントループを使用して接続とコマンドを処理して、データの原子性と一貫性を確保します。 Redisは、キーの有効期限を設定し、怠zyな削除メカニズムを使用して有効期限キーを削除します。

Redis-Serverが見つからない場合はどうすればよいですか Redis-Serverが見つからない場合はどうすればよいですか Apr 10, 2025 pm 06:54 PM

Redis-Serverが見つからない問題を解決するための手順:インストールを確認して、Redisが正しくインストールされていることを確認します。環境変数Redis_hostとredis_portを設定します。 Redis Server Redis-Serverを起動します。サーバーがRedis-Cli pingを実行しているかどうかを確認します。

Redisのすべてのキーを表示する方法 Redisのすべてのキーを表示する方法 Apr 10, 2025 pm 07:15 PM

Redisのすべてのキーを表示するには、3つの方法があります。キーコマンドを使用して、指定されたパターンに一致するすべてのキーを返します。スキャンコマンドを使用してキーを繰り返し、キーのセットを返します。情報コマンドを使用して、キーの総数を取得します。

Redisのソースコードを読み取る方法 Redisのソースコードを読み取る方法 Apr 10, 2025 pm 08:27 PM

Redisソースコードを理解する最良の方法は、段階的に進むことです。Redisの基本に精通してください。開始点として特定のモジュールまたは機能を選択します。モジュールまたは機能のエントリポイントから始めて、行ごとにコードを表示します。関数コールチェーンを介してコードを表示します。 Redisが使用する基礎となるデータ構造に精通してください。 Redisが使用するアルゴリズムを特定します。

Redisコマンドの使用方法 Redisコマンドの使用方法 Apr 10, 2025 pm 08:45 PM

Redis指令を使用するには、次の手順が必要です。Redisクライアントを開きます。コマンド(動詞キー値)を入力します。必要なパラメーターを提供します(指示ごとに異なります)。 Enterを押してコマンドを実行します。 Redisは、操作の結果を示す応答を返します(通常はOKまたは-ERR)。

Redisのバージョン番号を表示する方法 Redisのバージョン番号を表示する方法 Apr 10, 2025 pm 05:57 PM

Redisバージョン番号を表示するには、次の3つの方法を使用できます。(1)情報コマンドを入力し、(2) - versionオプションでサーバーを起動し、(3)構成ファイルを表示します。

Redisの有効期限ポリシーを設定する方法 Redisの有効期限ポリシーを設定する方法 Apr 10, 2025 pm 10:03 PM

Redisデータの有効期間戦略には2つのタイプがあります。周期削除:期限切れのキーを削除する定期的なスキャン。これは、期限切れの時間帯-remove-countおよび期限切れの時間帯-remove-delayパラメーターを介して設定できます。怠zyな削除:キーが読み取られたり書かれたりした場合にのみ、削除の有効期限が切れたキーを確認してください。それらは、レイジーフリーレイジーエビクション、レイジーフリーレイジーエクスピア、レイジーフリーラジーユーザーのパラメーターを介して設定できます。

See all articles