PHP 实现多服务器共享 SESSION 数据

代码实现,首先创建数据表,MySQL 的 SQL 语句如下:

  1. CREATE TABLE `sess` (
  2. `sesskey` varchar(32) NOT NULL default ”,
  3. `expiry` bigint(20) NOT NULL default ‘0′,
  4. `data` longtext NOT NULL,
  5. PRIMARY KEY (`sesskey`),
  6. KEY `expiry` (`expiry`)
  7. ) TYPE=MyISAM

sesskey 为 SESSION ID,expiry 为 SESSION 过期时间,data 用于保存 SESSION 数据,默认情况下 SESSION 数据是以文件方式保存,想要使用数据库方式保存,就必须重新定义 SESSION 各个操作的处理函数,PHP 提供了session_set_save_handle() 函数,可以用此函数自定义 SESSION 的处理过程,当然首先要先将 session.save_handler 改成 user,可在 PHP 中进行设置,代码如下:

<?php session_module_name(‘user‘); ?>

接下来着重讲一下 session_set_save_handle() 函数,此函数有六个参数:

session_set_save_handler(string open,string close,string read,string write,string destroy,string gc)

各个参数为各项操作的函数名,这些操作依次是:打开、关闭、读取、写入、销毁、垃圾回收,PHP 手册中有详细的例子,在这里我们使用 OO 的方式来实现这些操作,详细代码如下:

  1. <?php
  2. define(‘MY_SESS_TIME‘, 3600); //SESSION 生存时长
  3. //类定义
  4. class My_Sess
  5. {
  6. function init()
  7. {
  8. $domain = ‘.infor96.com‘;
  9. //不使用 GET/POST 变量方式
  10. ini_set(‘session.use_trans_sid‘, 0);
  11. //设置垃圾回收最大生存时间
  12. ini_set(‘session.gc_maxlifetime‘, MY_SESS_TIME);
  13. //使用 COOKIE 保存 SESSION ID 的方式
  14. ini_set(‘session.use_cookies‘, 1);
  15. ini_set(‘session.cookie_path‘, ‘/‘);
  16. //多主机共享保存 SESSION ID 的 COOKIE
  17. ini_set(‘session.cookie_domain‘, $domain);
  18. //将 session.save_handler 设置为 user,而不是默认的 files
  19. session_module_name(‘user‘);
  20. //定义 SESSION 各项操作所对应的方法名:
  21. session_set_save_handler(
  22. array(‘My_Sess‘, ‘open‘), //对应于静态方法 My_Sess::open(),下同。
  23. array(‘My_Sess‘, ‘close‘),
  24. array(‘My_Sess‘, ‘read‘),
  25. array(‘My_Sess‘, ‘write‘),
  26. array(‘My_Sess‘, ‘destroy‘),
  27. array(‘My_Sess‘, ‘gc‘)
  28. );
  29. } //end function
  30. function open($save_path, $session_name) {
  31. return true;
  32. } //end function
  33. function close() {
  34. global $MY_SESS_CONN;
  35. if ($MY_SESS_CONN) { //关闭数据库连接
  36. $MY_SESS_CONN->Close();
  37. }
  38. return true;
  39. } //end function
  40. function read($sesskey) {
  41. global $MY_SESS_CONN;
  42. $sql = ‘SELECT data FROM sess WHERE sesskey=‘ . $MY_SESS_CONN->qstr($sesskey) . ‘ AND expiry>=‘ . time();
  43. $rs =& $MY_SESS_CONN->Execute($sql);
  44. if ($rs) {
  45. if ($rs->EOF) {
  46. return ”;
  47. } else { //读取到对应于 SESSION ID 的 SESSION 数据
  48. $v = $rs->fields[0];
  49. $rs->Close();
  50. return $v;
  51. } //end if
  52. } //end if
  53. return ”;
  54. } //end function
  55. function write($sesskey, $data) {
  56. global $MY_SESS_CONN;
  57. $qkey = $MY_SESS_CONN->qstr($sesskey);
  58. $expiry = time() + My_SESS_TIME; //设置过期时间
  59. //写入 SESSION
  60. $arr = array(
  61. ‘sesskey‘ => $qkey,
  62. ‘expiry‘ => $expiry,
  63. ‘data‘ => $data);
  64. $MY_SESS_CONN->Replace(‘sess‘, $arr, ‘sesskey‘, $autoQuote = true);
  65. return true;
  66. } //end function
  67. function destroy($sesskey) {
  68. global $MY_SESS_CONN;
  69. $sql = ‘DELETE FROM sess WHERE sesskey=‘ . $MY_SESS_CONN->qstr($sesskey);
  70. $rs =& $MY_SESS_CONN->Execute($sql);
  71. return true;
  72. } //end function
  73. function gc($maxlifetime = null) {
  74. global $MY_SESS_CONN;
  75. $sql = ‘DELETE FROM sess WHERE expiry< ‘ . time();
  76. $MY_SESS_CONN->Execute($sql);
  77. //由于经常性的对表 sess 做删除操作,容易产生碎片,
  78. //所以在垃圾回收中对该表进行优化操作。
  79. $sql = ‘OPTIMIZE TABLE sess‘;
  80. $MY_SESS_CONN->Execute($sql);
  81. return true;
  82. } //end function
  83. } ///:~
  84. //使用 ADOdb 作为数据库抽象层。
  85. require_once(‘adodb/adodb.inc.php‘);
  86. //数据库配置项,可放入配置文件中(如:config.inc.php)。
  87. $db_type = ‘mysql‘;
  88. //开源代码phpfensi.com
  89. $db_host = ‘192.168.212.1‘;
  90. $db_user = ‘sess_user‘;
  91. $db_pass = ‘sess_pass‘;
  92. $db_name = ‘sess_db‘;
  93. //创建数据库连接,这是一个全局变量。
  94. $GLOBALS['MY_SESS_CONN'] =& ADONewConnection($db_type);
  95. $GLOBALS['MY_SESS_CONN']->Connect( $db_host, $db_user, $db_pass, $db_name);
  96. //初始化 SESSION 设置,必须在 session_start() 之前运行!!
  97. My_Sess::init();
  98. ?>