概述

这是关于 Swoole 入门学习的第九篇文章:Swoole Redis 连接池的实现。

收到读者反馈,“亮哥,文章能多点图片吗?就是将运行结果以图片的形式展示...”

我个人觉得这是比较懒、动手能力差的表现,恩... 要勤快些。

但谁让文章是写给你们看的那,我以后尽量文章写的图文并茂一点。

上篇文章 分享了 MySQL 连接池,这篇文章 咱们来分享下 Redis 连接池。

在上篇文章的基础上进行简单调整即可,将实例化 MySQL 的地方,修改成实例化 Redis 即可,还要注意一些方法的调整。

这篇文章仅仅只实现一个 Redis 连接池,篇幅就太少了,顺便将前几篇整合一下。

大概 Demo 中包含这些点:

实现 MySQL 连接池

实现 MySQL CURD 方法的定义

实现 Redis 连接池

实现 Redis 方法的定义

满足 HTTP、TCP、WebSocket 调用

提供 Demo 供测试

调整 目录结构

HTTP 调用:

实现 读取 MySQL 中数据的 Demo

实现 读取 Redis 中数据的 Demo

TCP 调用:

实现 读取 MySQL 中数据的 Demo

实现 读取 Redis 中数据的 Demo

WebSocket 调用:

实现 每秒展示 API 调用量 Demo

目录结构

├─ client

│ ├─ http

│ ├── mysql.php //测试 MySQL 连接

│ ├── redis.php //测试 Redis 连接

│ ├─ tcp

│ ├── mysql.php //测试 MySQL 连接

│ ├── redis.php //测试 Redis 连接

│ ├─ websocket

│ ├── index.html //实现 API 调用量展示

├─ controller

│ ├─ Order.php //实现 MySQL CURD

│ ├─ Product.php //实现 Redis 调用

│ ├─ Statistic.php //模拟 API 调用数据

├─ server

│ ├─ config

│ ├── config.php //默认配置

│ ├── mysql.php //MySQL 配置

│ ├── redis.php //Redis 配置

│ ├─ core

│ ├── Common.php //公共方法

│ ├── Core.php //核心文件

│ ├── HandlerException.php //异常处理

│ ├── callback //回调处理

│ ├── OnRequest.php

│ ├── OnReceive.php

│ ├── OnTask.php

│ ├── ...

│ ├── mysql

│ ├── MysqlDB.php

│ ├── MysqlPool.php

│ ├── redis

│ ├── RedisDB.php

│ ├── RedisPool.php

│ ├─ log -- 需要 读/写 权限

│ ├── ...

├─ index.php //入口文件

代码

server/core/redis/RedisPool.php

if (!defined('SERVER_PATH')) exit("No Access");

class RedisPool

{

private static $instance;

private $pool;

private $config;

public static function getInstance($config = null)

{

if (empty(self::$instance)) {

if (empty($config)) {

throw new RuntimeException("Redis config empty");

}

self::$instance = new static($config);

}

return self::$instance;

}

public function __construct($config)

{

if (empty($this->pool)) {

$this->config = $config;

$this->pool = new chan($config['master']['pool_size']);

for ($i = 0; $i < $config['master']['pool_size']; $i++) {

go(function() use ($config) {

$redis = new RedisDB();

$res = $redis->connect($config);

if ($res === false) {

throw new RuntimeException("Failed to connect redis server");

} else {

$this->pool->push($redis);

}

});

}

}

}

public function get()

{

if ($this->pool->length() > 0) {

$redis = $this->pool->pop($this->config['master']['pool_get_timeout']);

if (false === $redis) {

throw new RuntimeException("Pop redis timeout");

}

defer(function () use ($redis) { //释放

$this->pool->push($redis);

});

return $redis;

} else {

throw new RuntimeException("Pool length <= 0");

}

}

}

server/core/redis/RedisDB.php

if (!defined('SERVER_PATH')) exit("No Access");

class RedisDB

{

private $master;

private $slave;

private $config;

public function __call($name, $arguments)

{

// TODO 主库的操作

$command_master = ['set', 'hset', 'sadd'];

if (in_array($name, $command_master)) {

$db = $this->_get_usable_db('slave');

} else {

$db = $this->_get_usable_db('master');

}

$result = call_user_func_array([$db, $name], $arguments);

return $result;

}

public function connect($config)

{

//主库

$master = new Swoole\Coroutine\Redis();

$res = $master->connect($config['master']['host'], $config['master']['port']);

if ($res === false) {

throw new RuntimeException($master->errCode, $master->errMsg);

} else {

$this->master = $master;

}

//从库

$slave = new Swoole\Coroutine\Redis();

$res = $slave->connect($config['slave']['host'], $config['slave']['port']);

if ($res === false) {

throw new RuntimeException($slave->errCode, $slave->errMsg);

} else {

$this->slave = $slave;

}

$this->config = $config;

return $res;

}

private function _get_usable_db($type)

{

if ($type == 'master') {

if (!$this->master->connected) {

$master = new Swoole\Coroutine\Redis();

$res = $master->connect($this->config['master']['host'], $this->config['master']['port']);

if ($res === false) {

throw new RuntimeException($master->errCode, $master->errMsg);

} else {

$this->master = $master;

}

}

return $this->master;

} elseif ($type == 'slave') {

if (!$this->slave->connected) {

$slave = new Swoole\Coroutine\Redis();

$res = $slave->connect($this->config['slave']['host'], $this->config['slave']['port']);

if ($res === false) {

throw new RuntimeException($slave->errCode, $slave->errMsg);

} else {

$this->slave = $slave;

}

}

return $this->slave;

}

}

}

client/http/redis.php

$demo = [

'type' => 'SW',

'token' => 'Bb1R3YLipbkTp5p0',

'param' => [

'class' => 'Product',

'method' => 'set',

'param' => [

'key' => 'C4649',

'value' => '订单-C4649'

],

],

];

$ch = curl_init();

$options = [

CURLOPT_URL => 'http://10.211.55.4:9509/',

CURLOPT_POST => 1,

CURLOPT_POSTFIELDS => json_encode($demo),

];

curl_setopt_array($ch, $options);

curl_exec($ch);

curl_close($ch);

client/tpc/redis.php

class Client

{

private $client;

public function __construct() {

$this->client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);

$this->client->on('Connect', [$this, 'onConnect']);

$this->client->on('Receive', [$this, 'onReceive']);

$this->client->on('Close', [$this, 'onClose']);

$this->client->on('Error', [$this, 'onError']);

}

public function connect() {

if(!$fp = $this->client->connect("0.0.0.0", 9510, 1)) {

echo "Error: {$fp->errMsg}[{$fp->errCode}]".PHP_EOL;

return;

}

}

public function onConnect() {

fwrite(STDOUT, "测试RPC (Y or N):");

swoole_event_add(STDIN, function() {

$msg = trim(fgets(STDIN));

if ($msg == 'y') {

$this->send();

}

fwrite(STDOUT, "测试RPC (Y or N):");

});

}

public function onReceive($cli, $data) {

echo '[Received]:'.$data;

}

public function send() {

$demo = [

'type' => 'SW',

'token' => 'Bb1R3YLipbkTp5p0',

'param' => [

'class' => 'Product',

'method' => 'get',

'param' => [

'code' => 'C4649'

],

],

];

$this->client->send(json_encode($demo));

}

public function onClose() {

echo "Client close connection".PHP_EOL;

}

public function onError() {

}

}

$client = new Client();

$client->connect();

client/websocket/index.html

Demo

if ("WebSocket" in window) {

// 基于准备好的dom,初始化echarts实例

var myChart = echarts.init(document.getElementById('main'));

var wsServer = 'ws://10.211.55.4:9509';

var ws = new WebSocket(wsServer);

ws.onopen = function (evt) {

if (ws.readyState == 1) {

console.log('WebSocket 连接成功...');

} else {

console.log('WebSocket 连接失败...');

}

if (ws.readyState == 1) {

ws.send('开始请求...');

} else {

alert('WebSocket 连接失败');

}

};

ws.onmessage = function (evt) {

console.log('Retrieved data from server: ' + evt.data);

var evt_data = jQuery.parseJSON(evt.data);

myChart.setOption({

xAxis: {

data : evt_data.time

},

series: [{

data: evt_data.value

}]

});

};

ws.onerror = function (evt) {

alert('WebSocket 发生错误');

console.log(evt);

};

ws.onclose = function() {

alert('WebSocket 连接关闭');

console.log('WebSocket 连接关闭...');

};

// 指定图表的配置项和数据

$.ajax({

url : 'http://10.211.55.4:9509/', // 请求url

type : "post", // 提交方式

dataType : "json", // 数据类型

data : {

'type' : 'SW',

'token' : 'Bb1R3YLipbkTp5p0',

'param' : {

'class' : 'Statistic',

'method' : 'init'

}

},

beforeSend:function() {

},

success : function(rs) {

if (rs.code != 1) {

alert('获取数据失败');

} else {

var option = {

title: {

text: 'API 调用量',

x:'center'

},

tooltip: {

trigger: 'axis',

axisPointer: {

animation: false

}

},

xAxis: {

type : 'category',

data : rs.data.time

},

yAxis: {

type: 'value',

boundaryGap: [0, '100%'],

name: '使用量',

splitLine: {

show: false

}

},

series: [{

name: '使用量',

type: 'line',

showSymbol: false,

hoverAnimation: false,

data: rs.data.value

}]

};

// 使用刚指定的配置项和数据显示图表。

if (option && typeof option === "object") {

myChart.setOption(option, true);

}

}

},

error : function(){

alert('服务器请求异常');

}

});

} else {

alert("您的浏览器不支持 WebSocket!");

}

还涉及到,OnMessage.php、OnTask.php 、OnWorkerStart.php 等,就不贴代码了。

运行

小框架的启动/关闭/热加载,看看这篇文章: 第六篇:Swoole 整合成一个小框架

里面 Demo 在 client 文件夹下。

http 目录下的文件,放到自己虚拟目录下,用浏览器访问。

tcp 目录下的文件,在 CLI 下运行。

websocket 目录下的文件,直接点击在浏览器访问。

扩展

官方协程 Redis 客户端手册:

大家可以尝试使用官方提供的其他方法。

小结

Demo 代码仅供参考,里面有很多不严谨的地方,根据自己的需要进行修改 ...

上面的 Demo 需要源码的,加我微信。(菜单-> 加我微信-> 扫我)

本文欢迎转发,转发请注明作者和出处,谢谢!

easyswoole数据库连接池_Swoole Redis 连接池的实现相关推荐

  1. easyswoole数据库连接池_easyswoole redis连接池:集群迁移教程

    场景 在业务量小的情况下,我们使用Redis单机连接池就可以满足业务需求.因此,redis单机连接池就可以满足我们的业务.因此我们会这样写: 示例 注册连接池 use EasySwoole\Redis ...

  2. python redis连接池获取后关闭_python通过连接池连接redis,操作redis队列

    在每次使用redis都进行连接的话会拉低redis的效率,都知道redis是基于内存的数据库,效率贼高,所以每次进行连接比真正使用消耗的资源和时间还多.所以为了节省资源,减少多次连接损耗,连接池的作用 ...

  3. Java的Redis连接池代码性能不错

    其实这个是引用自网友http://blog.csdn.net/tuposky/article/details/45340183,有2个版本,差别就是ReentrantLock和synchronized ...

  4. 数据库连接池和Tomcat连接池的配置问题

    在做系统优化的时候师哥给我们提了一个连接池的概念,问我们有没有配置,我对这个概念一无所知,于是进行了一些研究,连接池有很多,比如WCF.EF还有数据库.CAS也可以配连接池,这些连接池用通俗的语言来说 ...

  5. redis连接池操作

    /** * @类描述 redis 工具 * @功能名 POJO * @author zxf * @date 2014年11月25日 */ public final class RedisUtil { ...

  6. java操作redis redis连接池

    redis作为缓存型数据库,越来越受到大家的欢迎,这里简单介绍一下java如何操作redis. 1.java连接redis java通过需要jedis的jar包获取Jedis连接. jedis-2.8 ...

  7. redis专题:redis键值设计、性能优化以及redis连接池配置

    文章目录 1.redis键值设计 ①:key设计规范 ②:value设计规范 2. 命令使用优化 3. redis连接池配置参数设计 4. redis连接池预热 5. redis的key过期删除策略 ...

  8. Java Redis 连接池 Jedis 工具类,java基础面试笔试题

    我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...

  9. Java的Redis连接池代码

    2019独角兽企业重金招聘Python工程师标准>>> 其实这个是引用自网友http://blog.csdn.net/tuposky/article/details/45340183 ...

  10. php redis 集群 长连接池,php如何实现redis连接池

    项目使用的是php,生产环境使用的是redis集群,连接的地址是配置的域名,每次创建连接必须要经过一次域名解析,频繁的创建链接效率低下且经常出现超时的情况,有没有在生产环境实现redis链接池的,分享 ...

最新文章

  1. 关闭linux服务器电源,linux关闭ACPI电源管理模块
  2. 吴恩达 coursera ML 第十四课总结+作业答案
  3. 一套优雅的 Go 错误问题解决方案
  4. codeforces 96A-C语言解题报告
  5. java+ssh+mysql酒店网站管理系统源码
  6. c语言变量生存期,C语言变量的生命周期
  7. 实现机器学习的循序渐进指南系列汇总
  8. 安卓c语言文档下载,C语言.NET技术09.doc
  9. iconfont 阿里巴巴矢量图标库 引入图标不显示
  10. 《高等代数学》(姚慕生),习题1.1:二阶行列式
  11. 基于python的多光谱影像植被指数计算
  12. KiCad 部分插件安装
  13. 【Java系列】(四)Java多线程---线程安全
  14. 【VUE】vue网站设计-----字节招聘网站设计
  15. C语言变量的存储方式和生存期
  16. 移动硬盘、U盘因中断原因变为只读模式解决办法
  17. Qt的QVector类
  18. 【数学建模】2022数维杯国际赛C题 如何利用脑结构特征和认知行为特征诊断阿尔茨海默病(How to Diagnose Alzheimer‘s Disease)
  19. 【声音 | 华兴资本包凡:未来新经济行业一定靠区块链等技术驱动】
  20. Xshell利用puTTYgen生成的ppk文件访问远程主机

热门文章

  1. MySQL Buffer Pool缓冲池总结
  2. MyBatis源码阅读(二) --- 执行流程分析
  3. 浅谈系统如何对接社交登录之微博登录功能
  4. JavaScript 获取小数任一小数点后的位数的小数
  5. shell脚本基础和grep使用
  6. 数据中心业务中断 多与运营流程有关
  7. 缺失索引自动创建语句
  8. 理清javascript的相关概念 DOM和BOM
  9. 百度要革自己的命?移动搜索或取消PC网页收录
  10. [JNI]开发之旅(6)JNI函数中访问java类中对象的属性