redis mysql 连接池 之 golang 实现
1 mysql 连接池代码
package lib import (
"database/sql"
"fmt"
"strconv" "github.com/arnehormann/sqlinternals/mysqlinternals"
_ "github.com/go-sql-driver/mysql"
) var MYSQL map[string]string = map[string]string{
"host": "127.0.0.1:3306",
"database": "",
"user": "",
"password": "",
"maxOpenConns": "0",
"maxIdleConns": "0",
} type SqlConnPool struct {
DriverName string
DataSourceName string
MaxOpenConns int64
MaxIdleConns int64
SqlDB *sql.DB // 连接池
} var DB *SqlConnPool func init() {
dataSourceName := fmt.Sprintf("%s:%s@tcp(%s)/%s", MYSQL["user"], MYSQL["password"], MYSQL["host"], MYSQL["database"])
maxOpenConns, _ := strconv.ParseInt(MYSQL["maxOpenConns"], 10, 64)
maxIdleConns, _ := strconv.ParseInt(MYSQL["maxIdleConns"], 10, 64) DB = &SqlConnPool{
DriverName: "mysql",
DataSourceName: dataSourceName,
MaxOpenConns: maxOpenConns,
MaxIdleConns: maxIdleConns,
}
if err := DB.open(); err != nil {
panic("init db failed")
}
} // 封装的连接池的方法
func (p *SqlConnPool) open() error {
var err error
p.SqlDB, err = sql.Open(p.DriverName, p.DataSourceName)
p.SqlDB.SetMaxOpenConns(int(p.MaxOpenConns))
p.SqlDB.SetMaxIdleConns(int(p.MaxIdleConns))
return err
} func (p *SqlConnPool) Close() error {
return p.SqlDB.Close()
} func (p *SqlConnPool) Query(queryStr string, args ...interface{}) ([]map[string]interface{}, error) {
rows, err := p.SqlDB.Query(queryStr, args...)
defer rows.Close()
if err != nil {
return []map[string]interface{}{}, err
}
// 返回属性字典
columns, err := mysqlinternals.Columns(rows)
// 获取字段类型
scanArgs := make([]interface{}, len(columns))
values := make([]sql.RawBytes, len(columns))
for i, _ := range values {
scanArgs[i] = &values[i]
}
rowsMap := make([]map[string]interface{}, 0, 10)
for rows.Next() {
rows.Scan(scanArgs...)
rowMap := make(map[string]interface{})
for i, value := range values {
rowMap[columns[i].Name()] = bytes2RealType(value, columns[i].MysqlType())
}
rowsMap = append(rowsMap, rowMap)
}
if err = rows.Err(); err != nil {
return []map[string]interface{}{}, err
}
return rowsMap, nil
} func (p *SqlConnPool) execute(sqlStr string, args ...interface{}) (sql.Result, error) {
return p.SqlDB.Exec(sqlStr, args...)
} func (p *SqlConnPool) Update(updateStr string, args ...interface{}) (int64, error) {
result, err := p.execute(updateStr, args...)
if err != nil {
return 0, err
}
affect, err := result.RowsAffected()
return affect, err
} func (p *SqlConnPool) Insert(insertStr string, args ...interface{}) (int64, error) {
result, err := p.execute(insertStr, args...)
if err != nil {
return 0, err
}
lastid, err := result.LastInsertId()
return lastid, err } func (p *SqlConnPool) Delete(deleteStr string, args ...interface{}) (int64, error) {
result, err := p.execute(deleteStr, args...)
if err != nil {
return 0, err
}
affect, err := result.RowsAffected()
return affect, err
} type SqlConnTransaction struct {
SqlTx *sql.Tx // 单个事务连接
} //// 开启一个事务
func (p *SqlConnPool) Begin() (*SqlConnTransaction, error) {
var oneSqlConnTransaction = &SqlConnTransaction{}
var err error
if pingErr := p.SqlDB.Ping(); pingErr == nil {
oneSqlConnTransaction.SqlTx, err = p.SqlDB.Begin()
}
return oneSqlConnTransaction, err
} // 封装的单个事务连接的方法
func (t *SqlConnTransaction) Rollback() error {
return t.SqlTx.Rollback()
} func (t *SqlConnTransaction) Commit() error {
return t.SqlTx.Commit()
} func (t *SqlConnTransaction) Query(queryStr string, args ...interface{}) ([]map[string]interface{}, error) {
rows, err := t.SqlTx.Query(queryStr, args...)
defer rows.Close()
if err != nil {
return []map[string]interface{}{}, err
}
// 返回属性字典
columns, err := mysqlinternals.Columns(rows)
// 获取字段类型
scanArgs := make([]interface{}, len(columns))
values := make([]sql.RawBytes, len(columns))
for i, _ := range values {
scanArgs[i] = &values[i]
}
rowsMap := make([]map[string]interface{}, 0, 10)
for rows.Next() {
rows.Scan(scanArgs...)
rowMap := make(map[string]interface{})
for i, value := range values {
rowMap[columns[i].Name()] = bytes2RealType(value, columns[i].MysqlType())
}
rowsMap = append(rowsMap, rowMap)
}
if err = rows.Err(); err != nil {
return []map[string]interface{}{}, err
}
return rowsMap, nil
} func (t *SqlConnTransaction) execute(sqlStr string, args ...interface{}) (sql.Result, error) {
return t.SqlTx.Exec(sqlStr, args...)
} func (t *SqlConnTransaction) Update(updateStr string, args ...interface{}) (int64, error) {
result, err := t.execute(updateStr, args...)
if err != nil {
return 0, err
}
affect, err := result.RowsAffected()
return affect, err
} func (t *SqlConnTransaction) Insert(insertStr string, args ...interface{}) (int64, error) {
result, err := t.execute(insertStr, args...)
if err != nil {
return 0, err
}
lastid, err := result.LastInsertId()
return lastid, err } func (t *SqlConnTransaction) Delete(deleteStr string, args ...interface{}) (int64, error) {
result, err := t.execute(deleteStr, args...)
if err != nil {
return 0, err
}
affect, err := result.RowsAffected()
return affect, err
} // others
func bytes2RealType(src []byte, columnType string) interface{} {
srcStr := string(src)
var result interface{}
switch columnType {
case "TINYINT":
fallthrough
case "SMALLINT":
fallthrough
case "INT":
fallthrough
case "BIGINT":
result, _ = strconv.ParseInt(srcStr, 10, 64)
case "CHAR":
fallthrough
case "VARCHAR":
fallthrough
case "BLOB":
fallthrough
case "TIMESTAMP":
fallthrough
case "DATETIME":
result = srcStr
case "FLOAT":
fallthrough
case "DOUBLE":
fallthrough
case "DECIMAL":
result, _ = strconv.ParseFloat(srcStr, 64)
default:
result = nil
}
return result
}
2 redis 连接池代码
package lib import (
"strconv"
"time" "github.com/garyburd/redigo/redis"
) var REDIS map[string]string = map[string]string{
"host": "127.0.0.1:6379",
"database": "0",
"password": "",
"maxOpenConns": "0",
"maxIdleConns": "0",
} var Cache *RedisConnPool type RedisConnPool struct {
redisPool *redis.Pool
} func init() {
Cache = &RedisConnPool{}
maxOpenConns, _ := strconv.ParseInt(REDIS["maxOpenConns"], 10, 64)
maxIdleConns, _ := strconv.ParseInt(REDIS["maxIdleConns"], 10, 64)
database, _ := strconv.ParseInt(REDIS["database"], 10, 64) Cache.redisPool = newPool(REDIS["host"], REDIS["password"], int(database), int(maxOpenConns), int(maxIdleConns))
if Cache.redisPool == nil {
panic("init redis failed!")
}
} func newPool(server, password string, database, maxOpenConns, maxIdleConns int) *redis.Pool {
return &redis.Pool{
MaxActive: maxOpenConns, // max number of connections
MaxIdle: maxIdleConns,
IdleTimeout: 10 * time.Second,
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", server)
if err != nil {
return nil, err
}
if _, err := c.Do("AUTH", password); err != nil {
c.Close()
return nil, err
}
if _, err := c.Do("select", database); err != nil {
c.Close()
return nil, err
}
return c, err
},
TestOnBorrow: func(c redis.Conn, t time.Time) error {
_, err := c.Do("PING")
return err
},
}
} // 关闭连接池
func (p *RedisConnPool) Close() error {
err := p.redisPool.Close()
return err
} // 当前某一个数据库,执行命令
func (p *RedisConnPool) Do(command string, args ...interface{}) (interface{}, error) {
conn := p.redisPool.Get()
defer conn.Close()
return conn.Do(command, args...)
} //// String(字符串)
func (p *RedisConnPool) SetString(key string, value interface{}) (interface{}, error) {
conn := p.redisPool.Get()
defer conn.Close()
return conn.Do("SET", key, value)
} func (p *RedisConnPool) GetString(key string) (string, error) {
// 从连接池里面获得一个连接
conn := p.redisPool.Get()
// 连接完关闭,其实没有关闭,是放回池里,也就是队列里面,等待下一个重用
defer conn.Close()
return redis.String(conn.Do("GET", key))
} func (p *RedisConnPool) GetBytes(key string) ([]byte, error) {
conn := p.redisPool.Get()
defer conn.Close()
return redis.Bytes(conn.Do("GET", key))
} func (p *RedisConnPool) GetInt(key string) (int, error) {
conn := p.redisPool.Get()
defer conn.Close()
return redis.Int(conn.Do("GET", key))
} func (p *RedisConnPool) GetInt64(key string) (int64, error) {
conn := p.redisPool.Get()
defer conn.Close()
return redis.Int64(conn.Do("GET", key))
} //// Key(键)
func (p *RedisConnPool) DelKey(key string) (interface{}, error) {
conn := p.redisPool.Get()
defer conn.Close()
return conn.Do("DEL", key)
} func (p *RedisConnPool) ExpireKey(key string, seconds int64) (interface{}, error) {
conn := p.redisPool.Get()
defer conn.Close()
return conn.Do("EXPIRE", key, seconds)
} func (p *RedisConnPool) Keys(pattern string) ([]string, error) {
conn := p.redisPool.Get()
defer conn.Close()
return redis.Strings(conn.Do("KEYS", pattern))
} func (p *RedisConnPool) KeysByteSlices(pattern string) ([][]byte, error) {
conn := p.redisPool.Get()
defer conn.Close()
return redis.ByteSlices(conn.Do("KEYS", pattern))
} //// Hash(哈希表)
func (p *RedisConnPool) SetHashMap(key string, fieldValue map[string]interface{}) (interface{}, error) {
conn := p.redisPool.Get()
defer conn.Close()
return conn.Do("HMSET", redis.Args{}.Add(key).AddFlat(fieldValue)...)
} func (p *RedisConnPool) GetHashMapString(key string) (map[string]string, error) {
conn := p.redisPool.Get()
defer conn.Close()
return redis.StringMap(conn.Do("HGETALL", key))
} func (p *RedisConnPool) GetHashMapInt(key string) (map[string]int, error) {
conn := p.redisPool.Get()
defer conn.Close()
return redis.IntMap(conn.Do("HGETALL", key))
} func (p *RedisConnPool) GetHashMapInt64(key string) (map[string]int64, error) {
conn := p.redisPool.Get()
defer conn.Close()
return redis.Int64Map(conn.Do("HGETALL", key))
}
redis mysql 连接池 之 golang 实现的更多相关文章
- nodejs + redis/mysql 连接池问题
nodejs + redis/mysql 连接池问题 需不需要连接池 连接池的作用主要是较少每次临时建立连接所带来的开销.初步一看,nodejs运行单线程上,它不能同时使用多个连接,乍一看是不需要连接 ...
- 解决Mysql连接池被关闭 ,hibernate尝试连接不能连接的问题。 (默认mysql连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池。系统发布第二天访问链接关闭问题。
解决Mysql连接池被关闭 ,hibernate尝试连接不能连接的问题. (默认MySQL连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池. 所以系统发布第二天访问会 ...
- Java Mysql连接池配置和案例分析--超时异常和处理
前言: 最近在开发服务的时候, 发现服务只要一段时间不用, 下次首次访问总是失败. 该问题影响虽不大, 但终究影响用户体验. 观察日志后发现, mysql连接因长时间空闲而被关闭, 使用时没有死链检测 ...
- MySQL连接池
1. using System; using System.Collections; using MySql.Data.MySqlClient; namespace Helper { /// < ...
- redis运用连接池报错解决
redis使用连接池报错解决redis使用十几小时就一直报异常 redis.clients.jedis.exceptions.JedisConnectionException: Could not g ...
- tomcat中使用mysql连接池的配置
1.下载相应的jar包,添加到工程中 需要下载的包主要有commons-pool2-2.2 commons-dbcp2-2.0.1-src commons-dbcp2-2.0.1 commons-c ...
- mysql连接池的使用工具类代码示例
mysql连接池代码工具示例(scala): import java.sql.{Connection,PreparedStatement,ResultSet} import org.apache.co ...
- 用swoole简单实现MySQL连接池
MySQL连接池 在传统的网站开发中,比如LNMP模式,由Nginx的master进程接收请求然后分给多个worker进程,每个worker进程再链接php-fpm的master进程,php-fpm再 ...
- 实现一个协程版mysql连接池
实现一个协程版的mysql连接池,该连接池支持自动创建最小连接数,自动检测mysql健康:基于swoole的chanel. 最近事情忙,心态也有点不积极.技术倒是没有落下,只是越来越不想写博客了.想到 ...
随机推荐
- 树状数组求区间和模板 区间可修改 参考题目:牛客小白月赛 I 区间
从前有个东西叫树状数组,它可以轻易实现一些简单的序列操作,比如单点修改,区间求和;区间修改,单点求值等. 但是我们经常需要更高级的操作,比如区间修改区间查询.这时候树状数组就不起作用了,只能选择写一个 ...
- Allure-pytest功能特性介绍
前言 Allure框架是一个灵活的轻量级多语言测试报告工具,它不仅以web的方式展示了简介的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息从dev/qa的角度来看,Al ...
- framework7 picker 具体使用
官网地址:https://framework7.io/docs/picker.html#dom-events <meta charset="UTF-8"> <me ...
- .Net Core WebApi简单创建及使用
按照目前的软件开发发展趋势中,不管是前后端分离还是提供数据服务,WebApi使用的越来越广泛,而且.NET Core也是我们.NET开发人员未来发展的趋势,所以说学会使用.NET Core Api是非 ...
- 【Offer】[34] 【二叉树中和为某一值的路径】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径.从树的根节点开始往下一直到叶节点所经过的节点形成一条路径.  ...
- 洛谷 P1525 关押罪犯 NOIp2010提高组 (贪心+并查集)
题目链接:https://www.luogu.org/problemnew/show/P1525 题目分析 通过分析,我们可以知道,这道题的抽象意义就是把一个带边权的无向图,分成两个点集,使得两个集合 ...
- FreeSql (十八)导航属性
导航属性是 FreeSql 的特色功能之一,可通过约定配置.或自定义配置对象间的关系. 导航属性有 OneToMany, ManyToOne, ManyToMany, OneToOne, Parent ...
- hive 包含操作(left semi join)(left outer join = in)迪卡尔积
目前hive不支持 in或not in 中包含查询子句的语法,所以只能通过left join实现. 假设有一个登陆表login(当天登陆记录,只有一个uid),和一个用户注册表regusers(当天注 ...
- Jmeter接口压力测试,Java.net.BindException: Address already in use: connect
Java.net.BindException: Address already in use: connect 问题原因: 操作系统会为TCP/IP服务预留临时端口,Jmeter在跑并发测试的时候每开 ...
- Python Api接口自动化测试框架 excel篇
工作原理: 测试用例在excel上编辑,使用第三方库xlrd,读取表格sheet和内容,sheetName对应模块名,Jenkins集成服务发现服务moduleName查找对应表单,运用第三方库req ...