C语言PHP扩展高性能数据库ORM框架ycdb(3) : 稳定的Redis连接池

18 篇文章 1 订阅
3 篇文章 0 订阅
本文介绍ycdb数据库ORM框架的使用方法,包括构建数据库连接池、执行SQL语句及事务处理等。同时,深入探讨了Redis连接池的配置与实现,通过Lua脚本和nginx配置,展示了如何创建和维护高效的Redis连接池。
摘要由CSDN通过智能技术生成

上一章:C语言PHP扩展高性能数据库ORM框架ycdb(2): 构建稳定的数据库连接池

目录:

  • Instruction
  • Requirement
  • 创建测试表
  • 在linux中编译ycdb
  • Start ycdatabase
  • 初始化ycdb连接
  • 原生SQL执行
  • 错误处理
  • Where 语句
  • Select 语句
  • Insert 语句
  • Replace 语句
  • Update 语句
  • Delete 语句
  • 完整例句
  • 数据库事务
  • 数据缓存
  • PHP数据库连接池
  • Redis 连接池方案

Redis连接池方案

同理,Redis也可以采用相同的方法解决连接池问题。

源码 github 地址:  https://github.com/caohao-php/ycdatabase

 

Redis连接池配置

~/openresty-pool/conf/nginx.conf , 

worker_processes  1;        #nginx worker 数量

error_log logs/error.log;   #指定错误日志文件路径

events {
    worker_connections 1024;
}

stream {
	lua_code_cache on;

	lua_check_client_abort on;

	server {
		listen unix:/tmp/redis_pool.sock;

		content_by_lua_block {
			local redis_pool = require "redis_pool"
			
			pool = redis_pool:new({ip = "127.0.0.1", port = 6379, auth = "password"})

			pool:run()
		}
	}
	
	server {

		listen unix:/tmp/mysql_pool.sock;
		
		content_by_lua_block {
			local mysql_pool = require "mysql_pool"
			
			local config = {host = "127.0.0.1", 
							user = "root", 
							password = "test", 
							database = "collect", 
							timeout = 2000, 
							max_idle_timeout = 10000, 
							pool_size = 200}
						   
			pool = mysql_pool:new(config)
			
			pool:run()
		}
	}
}

PHP代码

$redis = new Redis();
$redis->pconnect('/tmp/redis_pool.sock');
var_dump($redis->hSet("foo1", "vvvvv42", 2));
var_dump($redis->hSet("foo1", "vvvv", 33));
var_dump($redis->expire("foo1", 111));
var_dump($redis->hGetAll("foo1"));

Redis连接池Lua代码

 ~/openresty-pool/redis_pool.lua

local redis = require "resty.redis"

local assert = assert
local rawget = rawget
local setmetatable = setmetatable
local tonumber = tonumber
local byte = string.byte
local sub = string.sub

-- 解析请求
local function parse_request(sock)
    local line, err = sock:receive()
    
    if not line then
        if err == "timeout" then
            sock:close()
        end
        return nil, err
    end
    
    local result = line .. "\r\n"
    local prefix = byte(line)
    
    if prefix == 42 then -- char '*'
        local num = tonumber(sub(line, 2))
        if num <= 0 then
            return result
        end
        
        for i = 1, num do
            local res, err = parse_request(sock)
            if res == nil then
                return nil, err
            end
            result = result .. res
        end
        
    elseif prefix == 36 then -- char '$'
        local size = tonumber(sub(line, 2))
        if size <= 0 then
            return result
        end
        
        local res, err = sock:receive(size)
        if not res then
            return nil, err
        end
        
        local crlf, err = sock:receive(2)
        if not crlf then
            return nil, err
        end
        
        result = result .. res .. crlf
    end
    
    return result
end

-- 异常退出
local function exit(err)
    ngx.log(ngx.ERR, "Redis ERROR EXIT: [", err, "]")
    return ngx.exit(ngx.ERROR)
end

----------------------------------------
local _M = {}
_M._VERSION = "1.0"

function _M.new(self, config)
    local t = {
        _ip = config.ip or "127.0.0.1",
        _port = config.port or 6379,
        _auth = config.auth,
        _timeout = config.timeout or 1000,  -- default 1 sec
        _pool_size = config.pool_size or 100,
        _max_idle_timeout = config.max_idle_timeout or 10000
    }
    return setmetatable(t, { __index = _M })
end

function _M.run(self)
	local downstream_sock = assert(ngx.req.socket(true))
    
	-- 解析客户端请求
	local res, err = parse_request(downstream_sock)
	if not res then
		return exit("parse_request failed : " .. err)
	end
    
	-- 创建 redis 连接
	local red = redis:new()
	
	red:set_timeout(self._timeout)
	
	local ok, err = red:connect(self._ip, self._port)
	if not ok then
		return exit(err)
	end
        
	-- redis auth 授权
	if self._auth then
		local times = assert(red:get_reused_times())
		if times == 0 then
			local ok, err = red:auth(self._auth)
			if not ok then
				return exit("auth failed : " .. err)
			end
		end
	end
        
	-- 发送请求到 redis 
	local upstream_sock = rawget(red, "_sock")
	upstream_sock:send(res)
        
	-- 接收 redis 应答,并解析
	local res, err = parse_request(upstream_sock)
	if not res then
		return exit("receive from redis server error: " .. err)
	end
	
	-- 发送应答给客户端
	downstream_sock:send(res)
	
	-- 设置 redis 连接池
	local ok, err = red:set_keepalive(self._max_idle_timeout, self._pool_size)
	if not ok then
		ngx.log(ngx.ERR, "redis set_keepalive failed: [", err, "]")
	end
end

return _M

上一章:开源轻量级PHP数据库ORM框架ycdb(2): 构建稳定的数据库连接池 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值