C++单例模式
单例模式(Singleton Pattern,也称为单件模式),使用最广泛的设计模式之一。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
定义一个单例类:
- 私有化它的构造函数,以防止外界创建单例类的对象;
- 使用类的私有静态指针变量指向类的唯一实例;
- 使用一个公有的静态方法获取该实例。
根据静态指针变量的初始化时间,可以分成懒汉式(Lazy Singleton)和饿汉式(Eager Singleton):
懒汉式:
class Singleton
{
private:
static Singleton* instance;
private:
Singleton() {};
~Singleton() {};
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
public:
static Singleton* getInstance()
{
if(instance == NULL)
instance = new Singleton();
return instance;
}
};
// init static member
Singleton* Singleton::instance = NULL;
饿汉式:
class Singleton
{
private:
static Singleton instance;
private:
Singleton();
~Singleton();
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
public:
static Singleton& getInstance() {
return instance;
}
}
// initialize defaultly
Singleton Singleton::instance;
MySQL的C/S架构
MySQL是Client/Server 的架构模式,分为服务端和客户端,服务端仅一个,而客户端可以有多个,甚至每个Shell都能算一个单独的客户端,而服务器端设置了默认的最大连接数,一般是151个。我们使用的mysql是命令行客户端程序,而mysqld是服务端程序。
因此,我们的客户端与服务器端是需要连接的,这之间就需要协议啦,包括TCP协议,也包括了适用于本地通信的套接字、共享内存、命名管道等。
而MySQL的每一次连接在服务器端都有一个专门的线程来管理,并且采用的网络IO模型是select/poll,并非epoll(主要是因为 select/poll 可移植性好,很多系统都支持。而且 mysql 的瓶颈不在于网络连接上,对于连接数少,并且连接都很活跃的 mysql 而言,select/poll 是更好的选择。)
因此,我们也可以用mysql这个客户端去连接远程的数据库,采用如下命令:
mysql -h ip地址 数据库名 -u用户名 -p
mysql -h 192.168.12.12 db_name -uusername -p
端口默认是3306.
我们使用上述指令就是在建立一个连接:
我们边执行指令,边抓包,能发现每一次连接都会进行三次握手,这就形成一个TCP连接。
可想而知,如果我们一次性建立大量的连接,这些连接的握手时间会耗费大量的时间,故我们可以维护一个少量的连接,形成一个连接池,这样就不用频繁的握手去建立连接啦。
连接池
连接池(英语:connection pool)是维护的数据库连接的缓存,以便在将来需要对数据库发出请求时可以重用连接。 连接池用于提高在数据库上执行命令的性能。
对于一个连接池,我们有一些性能参数:
-
初始连接量:表示连接池事先会和MySQL Server创建initSize个数的connection连接,当 应用发起MySQL访问时,不用再创建和MySQL Server新的连接,直接从连接池中获取一个可用的连接 就可以,使用完成后,并不去释放connection,而是把当前connection再归还到连接池当中。
-
最大连接量:当并发访问MySQL Server的请求增多时,初始连接量已经不够使用了,此 时会根据新的请求数量去创建更多的连接给应用去使用,但是新创建的连接数量上限是maxSize,不能 无限制的创建连接,因为每一个连接都会占用一个socket资源,一般连接池和服务器程序是部署在一台 主机上的,如果连接池占用过多的socket资源,那么服务器就不能接收太多的客户端请求了。当这些连 接使用完成后,再次归还到连接池当中来维护。
-
最大空闲时间:当访问MySQL的并发请求多了以后,连接池里面的连接数量会动态 增加,上限是maxSize个,当这些连接用完再次归还到连接池当中。如果在指定的maxIdleTime里面, 这些新增加的连接都没有被再次使用过,那么新增加的这些连接资源就要被回收掉,只需要保持初始连 接量initSize个连接就可以了。
-
连接超时时间:当MySQL的并发请求量过大,连接池中的连接数量已经到达 maxSize了,而此时没有空闲的连接可供使用,那么此时应用从连接池获取连接无法成功,它通过阻塞 的方式获取连接的时间如果超过connectionTimeout时间,那么获取连接失败,无法访问数据库。