ホームページ  >  記事  >  バックエンド開発  >  redis/分散ファイル ストレージ システム/データベースはセッションを保存し、ロード バランシング クラスターでのセッションの不整合の問題を解決します。redissession_PHP チュートリアル

redis/分散ファイル ストレージ システム/データベースはセッションを保存し、ロード バランシング クラスターでのセッションの不整合の問題を解決します。redissession_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-12 08:59:03884ブラウズ

redis/分散ファイルストレージシステム/データベースはセッションを保存し、負荷分散クラスターでのセッションの不整合の問題を解決します

まず、セッションとCookieの類似点と相違点について話しましょう

セッションと Cookie は、一方がサーバー側に保存され、もう一方がクライアント側に保存されるというような一般的なものではありません

セッションはサーバー側に保存されますが、ブラウザーのセッションが常に同じである理由を想像してみてください (有効期限や終了はカウントされません)。 「PHPSESSID」という名前のブラウザ側のクックです。「PHPSESSID」クッキーには文字列が含まれています。この文字列はセッションをマークするために使用され、サーバーはこの Cookie を見つけると、サーバー側のセッション ファイル ストレージ ディレクトリに移動して「sess_PHPSESSID value」という名前のファイルを検索します (存在しない場合は作成します)。このファイル内には、保存されたセッション データ (シリアル化されたデータ) が含まれています

そのため、このファイルを削除しても、次回セッションを使用するときに同じ名前のファイルが再作成されます。もちろん、Cookieを削除した場合は、名前を変更する必要があります。

セッションはデフォルトで各サーバーのローカルディレクトリに保存され、対応する設定が「php.ini」にあります

サーバー側の設定:

session.save_handler = files (デフォルトは file で、セッションをサーバーに保存する方法を定義します。ファイルとは、セッションを一時ファイルに保存することを意味します。データベースなどの他の保存方法をカスタマイズしたい場合は、 「ユーザー」に設定する必要があります)

session.save_path = "D:/wamp/php/sessiondata/" (サーバーがセッションを保存する一時ファイルの場所を定義します)

session.auto_start = 0 (1に設定すると、各ファイルに session_start() を記述する必要がなく、セッションが自動的に開始されます:)

session.gc_probability = 1


session.gc_divisor = 100

session.gc_maxlifetime = 1440 (上記の 3 つはセッションの自動ガベージ コレクション メカニズムを構成し、session.gc_probability と session.gc_divisor はセッション クリーンアップを実行する確率を構成します。理論上説明 サーバーは定期的に gc 関数を呼び出して、一定の確率でセッションをクリーンアップします。 クリーンアップの確率は次のとおりです。 たとえば、1/100 は、新しいセッションが初期化されるたびに、1% の確率でセッションがクリーンアップされることを意味します。ガベージコレクションメカニズムによってリサイクルされます。クリーニングの基準は、session.gc_maxlifetime)
で定義された時間です。

クライアント関連の設定もいくつかあります

session.use_cookies = 1 (クライアント上のセッション ID の保存方法。1 を設定すると、Cookie を使用してクライアントのセッション ID を記録します。同時に、クッキー $_COOKIE['PHPSESSIONID'] が $_COOKIE 変数に存在します。

session.use_only_cookies = 1 (クライアント上のセッション ID によって使用される保存方法も定義します。1 を設定すると、セッション ID の保存に Cookie のみを使用することを意味します)

session.use_trans_sid = 0 (上記の設定に対応します。ここで 1 に設定すると、セッション ID が url パラメーターを介して渡されることが許可されることを意味します。同様に、0 に設定することをお勧めします。そのため、ここにいくつかのインタビューがありますCookie を無効にしてもセッションを使用できるかどうかを修正するための質問です。答えは、もちろん、値を 1) に設定するだけです。

session.referer_check = (この設定は session.use_trans_sid = 1 の場合にのみ有効です。目的は、HTTP ヘッダーの「Referer」をチェックして、URL に含まれるセッション ID が有効かどうかを判断することです。HTTP_REFERER には次の文字が含まれている必要がありますこのパラメータで指定されている場合、URL 内のセッション ID は無効とみなされ、通常はデフォルトで空、つまりチェックされません)

session.name = PHPSESSID (sessionid の名前、つまり変数名を定義します。つまり、ブラウザ http ツールから見える http ヘッダー ファイル内の PHPSESSID = ##############)

session.cookie_lifetime = 0 (セッション ID を保存する Cookie ファイルのライフサイクル。0 に設定すると、セッションが終了し、セッション ID は自動的に消えます。ブラウザを強制的に閉じると、最後のセッション ID が失われます。失われた)



上記のことから、デフォルトではセッションは各サーバーにローカルに保存されることがわかります。そのため、クラスター環境でセッションを使用したい場合、デフォルトの構成を使用すると問題が発生します。つまり、クライアントはサーバー A のセッション ファイルにアクセスしたところです。セッション ファイルは A に存在しますが、後で顧客 B サーバーに割り当てられる可能性があります。この時点では、ファイルは B サーバーに存在せず、データは失われます。

以上です。問題の解決策は、データベース、Redis、またはファイル サーバーのいずれかにセッションを別のサーバーに保存することです

ここで作者が設定方法を一つ一つ解説しています

1. Redis を使用してセッションを保存します

この著者は最も単純なものについてのみ説明します。多くの人が使用しているものを使用する代わりに、それを保存する方法を規定する PHP クラスを作成する必要があります (もちろん、特別なニーズがある場合はこれを行うこともできます)。

まずphp.ini設定を変更します

リーリー

もちろん、phpプログラムで設定することもできます

リーリー

Redis でパスワードが設定されている場合は、次のように設定できます

リーリー

2. ファイルサーバーを使用してセッションを保存します

这个笔者觉得比较简单,笔者公司里面直接把分布式文件服务器挂载到指定目录下,然后访问分布式文件服务器就像访问本地文件夹一样,这里只需要设置下 保存路径即可

session.save_path = <span>"</span><span>xxxx</span><span>"</span>

 

三、使用数据库存放session

这个略显复杂,要写个PHP类,指定如何打开、读取、写入、销毁、GC垃圾回收、关闭,不过笔者不懒还是手动写一个意思意思

<?<span>php 
</span><span>class</span><span> sessionHandler{
    </span><span>/*</span><span>*
    * session 存放的库
    </span><span>*/</span>
    <span>const</span> SESSION_DB = 'mytest'<span>;

    </span><span>/*</span><span>*
    * session 存放的表
    </span><span>*/</span>
    <span>const</span> SESSION_TABLE = 'session'<span>;

    </span><span>/*</span><span>*
    * @var string $_dbHandler 数据库链接句柄
    </span><span>*/</span>
    <span>private</span> <span>$_dbHandler</span><span>;

    </span><span>/*</span><span>*
    * @var string $_dbHost 数据库主机
    </span><span>*/</span>
    <span>private</span> <span>$_dbHost</span><span>;

    </span><span>/*</span><span>*
    * @var string $_dbUser 数据库用户名
    </span><span>*/</span>
    <span>private</span> <span>$_dbUser</span><span>;

    </span><span>/*</span><span>*
    * @var string $_dbUser 数据库密码
    </span><span>*/</span>
    <span>private</span> <span>$_dbPasswd</span><span>;

    </span><span>/*</span><span>*
    * @var string $_name session 名称
    </span><span>*/</span>
    <span>private</span> <span>$_name</span><span>;

    </span><span>/*</span><span>*
    * 构造函数
    * @param string $dbHost 数据库主机
    * @param string $dbUser 数据库用户名
    * @param string $dbPasswd 数据库密码
    * @return void
    </span><span>*/</span>
    <span>public</span> <span>function</span> __construct(<span>$dbHost</span>, <span>$dbUser</span>, <span>$dbPasswd</span><span>)
    {
        </span><span>$this</span>->_dbHost = <span>$dbHost</span><span>;
        </span><span>$this</span>->_dbUser = <span>$dbUser</span><span>;
        </span><span>$this</span>->_dbPasswd = <span>$dbPasswd</span><span>;
    }

    </span><span>/*</span><span>*
    * 链接数据库
    * @param string $savePath 存储路径
    * @param string $name 名称
    * @return boolean
    </span><span>*/</span>
    <span>public</span> <span>function</span> open(<span>$savePath</span>, <span>$name</span><span>)
    {
        </span><span>$this</span>->_dbHandler = <span>mysql_connect</span>(<span>$this</span>->_dbHost, <span>$this</span>->_dbUser, <span>$this</span>-><span>_dbPasswd);
        </span><span>if</span>(!<span>$this</span>-><span>_dbHandler)
        {
            </span><span>return</span> <span>false</span><span>;
        }
        </span><span>$this</span>->_name = <span>$name</span><span>;
        </span><span>mysql_select_db</span>(self::SESSION_DB, <span>$this</span>-><span>_dbHandler);
        </span><span>return</span> <span>true</span><span>;
    }

    </span><span>/*</span><span>*
    * 读session
    * @param string $sessionId session id
    * @return mixd 存在返回数组  否则返回空
    </span><span>*/</span>
    <span>public</span> <span>function</span> read(<span>$sessionId</span><span>)
    {
        </span><span>$data</span> = ''<span>;
        </span><span>$sql</span> = <span>sprintf</span>('SELECT `data` FROM ' . self::SESSION_TABLE . ' WHERE `id`="%s"', <span>$sessionId</span><span>);
        </span><span>$result</span> = <span>mysql_query</span>(<span>$sql</span>, <span>$this</span>-><span>_dbHandler);
        </span><span>if</span>(<span>mysql_num_rows</span>(<span>$result</span>) == 1<span>)
        {
            </span><span>list</span>(<span>$data</span>) = <span>mysql_fetch_array</span>(<span>$result</span>,<span> MYSQL_NUM);
        }
        </span><span>return</span> <span>$data</span><span>;
    }

    </span><span>/*</span><span>*
    * 链接数据库
    * @param string $sessionId session id
    * @param string $data 数据
    * @return boolean
    </span><span>*/</span>
    <span>public</span> <span>function</span> write(<span>$sessionId</span>, <span>$data</span><span>)
    {
        </span><span>$sql</span> = <span>sprintf</span><span>(
                </span>'<span>REPLACE INTO 
                </span>' . self::SESSION_TABLE . '<span> (`id`, `data`, `last_time`) 
                VALUES 
                ("%s", "%s", %d)</span>', 
                <span>$sessionId</span>,     
                <span>mysql_escape_string</span>(<span>$data</span>),  
                <span>time</span><span>()
                );
        </span><span>mysql_query</span>(<span>$sql</span>, <span>$this</span>-><span>_dbHandler);
        </span><span>return</span> <span>mysql_affected_rows</span>(<span>$this</span>->_dbHandler) > 0<span>;
    }

    </span><span>/*</span><span>*
    * 链接数据库
    * @param int $expire 生存周期
    * @return boolean
    </span><span>*/</span>
    <span>public</span> <span>function</span> gc(<span>$expire</span><span>)
    {
        </span><span>$sql</span> = <span>sprintf</span><span>(
                        </span>'DELETE FROM `' . self::SESSION_TABLE . '<span>`
                        WHERE 
                        `last_time` < NOW() - %d</span>',
                        <span>$expire</span><span>
                    );
        </span><span>mysql_query</span>(<span>$sql</span>, <span>$this</span>-><span>_dbHandler);
        </span><span>return</span> <span>mysql_affected_rows</span>(<span>$this</span>->_dbHandler) > 0<span>;
    }

    </span><span>/*</span><span>*
    * 关闭数据库链接
    * @param void
    * @return boolean
    </span><span>*/</span>
    <span>public</span> <span>function</span><span> close()
    {
        </span><span>return</span> <span>mysql_close</span>(<span>$this</span>-><span>_dbHandler);
    }

    </span><span>/*</span><span>*
    * 销毁session
    * @param string $sessionId
    * @return boolean
    </span><span>*/</span>
    <span>public</span> <span>function</span> destroy(<span>$sessionId</span><span>)
    {
        </span><span>$sql</span> = <span>sprintf</span>('DELETE FROM `' . self::SESSION_TABLE . '` WHERE `id`="%s"', <span>$sessionId</span><span>);
        </span><span>mysql_query</span>(<span>$sql</span>, <span>$this</span>-><span>_dbHandler);
        </span><span>$_SESSION</span> = <span>array</span><span>();
        </span><span>return</span> <span>mysql_affected_rows</span>(<span>$this</span>->_dbHandler) > 0<span>;
    }
}


</span><span>$sessionHandler</span> = <span>new</span> sessionHandler('localhost', 'root', '123abc+'<span>);
</span><span>session_set_save_handler</span><span>(
                            </span><span>array</span>(<span>$sessionHandler</span>, 'open'),
                            <span>array</span>(<span>$sessionHandler</span>, 'close'),
                            <span>array</span>(<span>$sessionHandler</span>, 'read'),
                            <span>array</span>(<span>$sessionHandler</span>, 'write'),
                            <span>array</span>(<span>$sessionHandler</span>, 'destroy'),
                            <span>array</span>(<span>$sessionHandler</span>, 'gc'<span>)
                        );


</span><span>/*</span><span>
    在 PHP 5.0.5 中,在对象销毁之后才会调用 write 和 close 回调函数, 所以,在这两个回调函数中不可以使用对象,也不可以抛出异常。 
    如果在函数中抛出异常,PHP 既不会捕获它,也不会跟踪它, 这样会导致程序异常终止。 
    但是对象析构函数可以使用会话。
    可以在析构函数中调用 session_write_close() 函数来解决这个问题。 
    但是注册 shutdown 回调函数才是更加可靠的做法
</span><span>*/</span>
<span>register_shutdown_function</span>('session_write_close'<span>);

</span><span>session_start</span><span>();
</span><span>$_SESSION</span>['test'] = 'aa';

然后了建立一个表 叫 session  ,记住先建立数据库'mytest'奥  session表中有三个字段

id   vchar(100)  primary  sessionid的主键

data vchar(1000) 数据内容(序列化后的)

last_time int(10)  最后修改的时间戳

 

整完了运行下发现表里面的内容

大家可以看得出,通过代码自定义session的这种方式不仅可以应用到数据库上,也可以使用其他的,如文件、redis之类

 

 

至此,session的原理,如何自定义存放session,在集群中如何使用session,就已经完了

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1100144.htmlTechArticleredis/分布式文件存储系统/数据库 存储session,解决负载均衡集群中session不一致问题,redissession 先来说下session和cookie的异同 session和cookie不...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。