• 基于docker的mongodb安装以及PHP使用


    说明:用docker基于单服务器,虚拟多个服务器的方案,

    以下是两个config服务器,两个分片,以及每个分片有一个副本的方案

    这里关于给mongodb设置远程密码的问题,我采取了用两个compser文件来解决的方式

    也就是先不给mongodb配置keyfile(默认就是这样的),任何人都可以连到mongodb,且有权限访问和创建database。

    启动docker-compose-no-auth.yml后,创建admin账号和密码。

    已经创建了管理员帐号了,然后再来设置mongodb需要账号密码访问,其他子账号都可以由admin去分配。

    停掉之前的docker-compose-no-auth.yml

    然后再次启动docker-compose-auth.yml

    这样通过依次配置两个compose文件来解决设置mongodb远程连接的问题。

    如果你有更好的方式,请给我留言,非常感谢!

    1、安装docker

    #前往阿里云,搜索<容器镜像服务>开启服务
    
    #安装参考阿里云文档
    https://yq.aliyun.com/articles/110806?spm=5176.8351553.0.0.320d19912gmHZ6
    
    #开启镜像加速使用阿里云镜像服务器
    #进入阿里云<容器镜像服务> -- <镜像中心> -- <镜像加速器>
    #按里面的步骤添加配置
    

     

    2、安装docker-composer

    #参考官方文档https://docs.docker.com/compose/install/
    sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    sudo chmod +x /usr/local/bin/docker-compose
    docker-compose --version 

     

    3、启动docker-compose文件

    首先启动,这时还没有设置远程账号密码

    docker-compose-no-auth.yml

    version: '3'
    services:
    
      # config服务器一
      config_one:
        container_name: config_one
        image: mongo:4.1.11
        ports:
          - 27051:27019
        volumes:
          - ./config_one/db:/data/db
          - ./config_one/configdb:/data/configdb
        command: --configsvr --replSet "rs_config" --bind_ip_all
        restart: always
    
      # config服务器二
      config_two:
        container_name: config_two
        image: mongo:4.1.11
        ports:
          - 27052:27019
        volumes:
          - ./config_two/db:/data/db
          - ./config_two/configdb:/data/configdb
        command: --configsvr --replSet "rs_config" --bind_ip_all
        restart: always
    
      # 分片一的副本a
      shard_one_a:
        container_name: shard_one_a
        image: mongo:4.1.11
        ports:
          - 27011:27018
        volumes:
          - ./shard_one_a/db:/data/db
          - ./shard_one_a/configdb:/data/configdb
          - ./shard_one_a/backup:/data/backup
        command: --shardsvr --replSet "rs_shard_one_cluster" --bind_ip_all
        restart: always
        depends_on:
          - config_one
          - config_two
    
      # 分片二的副本a
      shard_two_a:
        container_name: shard_two_a
        image: mongo:4.1.11
        ports:
          - 27012:27018
        volumes:
          - ./shard_two_a/db:/data/db
          - ./shard_two_a/configdb:/data/configdb
          - ./shard_two_a/backup:/data/backup
        command: --shardsvr --replSet "rs_shard_two_cluster" --bind_ip_all
        restart: always
        depends_on:
          - config_one
          - config_two
    
      # 分片一的副本b
      shard_one_b:
        container_name: shard_one_b
        image: mongo:4.1.11
        ports:
          - 27021:27018
        volumes:
          - ./shard_one_b/db:/data/db
          - ./shard_one_b/configdb:/data/configdb
          - ./shard_one_b/backup:/data/backup
        command: --shardsvr --replSet "rs_shard_one_cluster" --bind_ip_all
        restart: always
        depends_on:
          - config_one
          - config_two
    
      # 分片二的副本b
      shard_two_b:
        container_name: shard_two_b
        image: mongo:4.1.11
        ports:
          - 27022:27018
        volumes:
          - ./shard_two_b/db:/data/db
          - ./shard_two_b/configdb:/data/configdb
          - ./shard_two_b/backup:/data/backup
        command: --shardsvr --replSet "rs_shard_two_cluster" --bind_ip_all
        restart: always
        depends_on:
          - config_one
          - config_two
          
      # mongos服务器一
      mongos_one:
        container_name: mongos-one
        image: mongo:4.1.11
        ports:
          - 27001:27017
        volumes:
          - ./mongos_one/db:/data/db
          - ./mongos_one/configdb:/data/configdb
        entrypoint: mongos
        command: --configdb rs_config/192.168.10.188:27051,192.168.10.188:27052 --bind_ip_all
        depends_on:
          - shard_one_a
          - shard_two_a
    
      # mongos服务器二
      mongos_two:
        container_name: mongos-two
        image: mongo:4.1.11
        ports:
          - 27002:27017
        volumes:
          - ./mongos_two/db:/data/db
          - ./mongos_two/configdb:/data/configdb
        entrypoint: mongos
        command: --configdb rs_config/192.168.10.188:27051,192.168.10.188:27052 --bind_ip_all
        depends_on:
          - shard_one_b
          - shard_two_b
    

     

    4、配置分片,添加管理员

    # 连接到任意一台配置服务器,初始化配置服副本
    docker exec -it config_one /bin/bash
    mongo --host localhost --port 27019
    rs.initiate({
        _id: "rs_config",
        configsvr: true,
        members: [
            { _id : 0, host : "172.19.60.174:27101" },
            { _id : 1, host : "172.19.60.175:27101" }
        ]
    });
    rs.status()
    
    # 连接到分片一,配置副本a、b
    docker exec -it shard_one_a /bin/bash
    mongo --host localhost --port 27018
    
    rs.initiate({
        _id: "rs_shard_one_cluster",
        members: [
            { _id : 0, host : "172.19.60.174:27201" },
            { _id : 1, host : "172.19.60.175:27201" }
        ]
    });
    rs.status()
    
    # 连接到分片二,配置副本a、b
    docker exec -it shard_two_a /bin/bash
    mongo --host localhost --port 27018
    
    rs.initiate({
        _id: "rs_shard_two_cluster",
        members: [
            { _id : 0, host : "172.19.60.174:27202" },
            { _id : 1, host : "172.19.60.175:27202" }
        ]
    });
    rs.status()
    
    # 连接到mongos服务器,添加分片
    docker exec -it mongos-one /bin/bash
    mongo --host localhost --port 27017
    sh.addShard("rs_shard_one_cluster/172.19.60.174:27201,172.19.60.175:27201");
    sh.addShard("rs_shard_two_cluster/172.19.60.174:27202,172.19.60.175:27202");
    sh.status()
    
    docker exec -it mongos-two /bin/bash
    mongo --host localhost --port 27017
    sh.addShard("rs_shard_one_cluster/172.19.60.174:27201,172.19.60.175:27201");
    sh.addShard("rs_shard_two_cluster/172.19.60.174:27202,172.19.60.175:27202");
    sh.status()
    
    //为数据库启动分片
    sh.enableSharding("test")
    //在需要分片的集合上对分片键建索引
    //如果集合是空的,可以不创建索引直接进行下一步的分片会自动创建索引
    //如果集合不为空,必须为分片建创建索引才行
    db.test.ensureIndex({"id":1})
    
    //设置分片键
    //其中第一种是基于hash的分片,第二种为基于值的分片
    sh.shardCollection( "test.student", { "id" : "hashed" } )
    sh.shardCollection("test.teacher", { "id" : 1 } )
    
    //查看片的状态
    sh.status();
    //查看片状态(完整版);
    printShardingStatus(db.getSisterDB("config"),1);
    //查看所有的分片服务器状态
    db.stats();
    
    //测试分片数据
    use test
    for (var i = 1; i <= 1000; i++) {
      db.student.insert( { "id" : i , "name": "student" + i } )
    }
    
    //分别连接到两个mongos, 分片一主副节点,分片二主副节点,查看是否数据都有
    use test
    db.student.find().sort({id:1});
    
    //生成管理员账号
    docker exec -it mongos-one /bin/bash
    mongo --host localhost --port 27017
    use admin
    db.runCommand({ 
        "createUser" : "root", 
        "pwd" : "root^mongo", 
        "customData" : {
    
        }, 
        "roles" : [
            {
                "role" : "dbAdminAnyDatabase", 
                "db" : "admin"
            }, 
            {
                "role" : "readWriteAnyDatabase", 
                "db" : "admin"
            }, 
            {
                "role" : "root", 
                "db" : "admin"
            }
        ]
    });
    

    5、生成keyfile

    //生成keyfile
    openssl rand -base64 756 > mongo-keyfile.jks
    chmod 400 mongo-keyfile.jks
    

     

    6、配置密钥,使mongodb访问需要带密码

    带keyfile的docker-compose-auth.yml

    version: '3'
    services:
    
      # config服务器一
      config_one:
        container_name: config_one
        image: mongo:4.1.11
        ports:
          - 27051:27019
        volumes:
          - ./config_one/db:/data/db
          - ./config_one/configdb:/data/configdb
          - ./mongo-keyfile.jks:/data/configdb/mongo-keyfile.jks
        command: --keyFile /data/configdb/mongo-keyfile.jks --configsvr --replSet "rs_config" --bind_ip_all
        restart: always
    
      # config服务器二
      config_two:
        container_name: config_two
        image: mongo:4.1.11
        ports:
          - 27052:27019
        volumes:
          - ./config_two/db:/data/db
          - ./config_two/configdb:/data/configdb
          - ./mongo-keyfile.jks:/data/configdb/mongo-keyfile.jks
        command: --keyFile /data/configdb/mongo-keyfile.jks --configsvr --replSet "rs_config" --bind_ip_all
        restart: always
    
      # 分片一的副本a
      shard_one_a:
        container_name: shard_one_a
        image: mongo:4.1.11
        ports:
          - 27011:27018
        volumes:
          - ./shard_one_a/db:/data/db
          - ./shard_one_a/configdb:/data/configdb
          - ./shard_one_a/backup:/data/backup
          - ./mongo-keyfile.jks:/data/configdb/mongo-keyfile.jks
        command: --keyFile /data/configdb/mongo-keyfile.jks --shardsvr --replSet "rs_shard_one_cluster" --bind_ip_all
        restart: always
        depends_on:
          - config_one
          - config_two
    
      # 分片二的副本a
      shard_two_a:
        container_name: shard_two_a
        image: mongo:4.1.11
        ports:
          - 27012:27018
        volumes:
          - ./shard_two_a/db:/data/db
          - ./shard_two_a/configdb:/data/configdb
          - ./shard_two_a/backup:/data/backup
          - ./mongo-keyfile.jks:/data/configdb/mongo-keyfile.jks
        command: --keyFile /data/configdb/mongo-keyfile.jks --shardsvr --replSet "rs_shard_two_cluster" --bind_ip_all
        restart: always
        depends_on:
          - config_one
          - config_two
    
      # 分片一的副本b
      shard_one_b:
        container_name: shard_one_b
        image: mongo:4.1.11
        ports:
          - 27021:27018
        volumes:
          - ./shard_one_b/db:/data/db
          - ./shard_one_b/configdb:/data/configdb
          - ./shard_one_b/backup:/data/backup
          - ./mongo-keyfile.jks:/data/configdb/mongo-keyfile.jks
        command: --keyFile /data/configdb/mongo-keyfile.jks --shardsvr --replSet "rs_shard_one_cluster" --bind_ip_all
        restart: always
        depends_on:
          - config_one
          - config_two
    
      # 分片二的副本b
      shard_two_b:
        container_name: shard_two_b
        image: mongo:4.1.11
        ports:
          - 27022:27018
        volumes:
          - ./shard_two_b/db:/data/db
          - ./shard_two_b/configdb:/data/configdb
          - ./shard_two_b/backup:/data/backup
          - ./mongo-keyfile.jks:/data/configdb/mongo-keyfile.jks
        command: --shardsvr --replSet "rs_shard_two_cluster" --keyFile /data/configdb/mongo-keyfile.jks --bind_ip_all
        restart: always
        depends_on:
          - config_one
          - config_two
          
      # mongos服务器一
      mongos_one:
        container_name: mongos-one
        image: mongo:4.1.11
        ports:
          - 27001:27017
        volumes:
          - ./mongos_one/db:/data/db
          - ./mongos_one/configdb:/data/configdb
          - ./mongo-keyfile.jks:/data/configdb/mongo-keyfile.jks
        entrypoint: mongos
        command:  --keyFile /data/configdb/mongo-keyfile.jks --configdb rs_config/192.168.10.188:27051,192.168.10.188:27052 --bind_ip_all
        depends_on:
          - shard_one_a
          - shard_two_a
    
      # mongos服务器二
      mongos_two:
        container_name: mongos-two
        image: mongo:4.1.11
        ports:
          - 27002:27017
        volumes:
          - ./mongos_two/db:/data/db
          - ./mongos_two/configdb:/data/configdb
          - ./mongo-keyfile.jks:/data/configdb/mongo-keyfile.jks
        entrypoint: mongos
        command: --keyFile /data/configdb/mongo-keyfile.jks --configdb rs_config/192.168.10.188:27051,192.168.10.188:27052 --bind_ip_all
        depends_on:
          - shard_one_b
          - shard_two_b
    

      

    注意mongo-keyfile.jks放的目录位置,最后再次启动docker,这时候的mongodb访问就需要账号密码了

    docker-compose -f docker-compose-auth.yml up -d
    

      

    7、安装php mongodb扩展

    扩展源码下载地址:http://pecl.php.net/package/mongodb
    
    wget -c https://pecl.php.net/get/mongodb-1.5.4.tgz
    
    tar -zxvf mongodb-1.5.4.tgz
    
    cd mongodb-1.5.4
    
    /www/server/php/72/bin/phpize
    
    ./configure --with-php-config=/www/server/php/72/bin/php-config
    
    make && make install
    
    vim /www/server/php/72/etc/php.ini
    
    extension = /www/server/php/72/lib/php/extensions/no-debug-non-zts-20170718/mongodb.so
    

     

    8、封装mongodb使用类

    我这里开始使用的thinkphp5官方给的mongodb连接库

    参考:

    https://packagist.org/packages/noprom/think-mongo-extend

    https://www.kancloud.cn/manual/thinkphp5/167865

    后来发现tp5官方的库,太难用了,做不了复杂的条件查询,于是自己写了一个,

    最后面有使用的示例,php mongodb官方有更多很详细的复杂查询的示例,使用文档参考:

    https://www.php.net/mongodb

    Connection.php

    <?php
    
    namespace apputilmongo;
    
    use MongoDBDriverBulkWrite;
    use MongoDBDriverCommand;
    use MongoDBDriverQuery;
    use MongoDBDriverManager;
    
    class Connection
    {
        protected $config = [];
        protected $server = [];
        protected $manager;
    
        public function __construct(array $config = [])
        {
            if (!class_exists('MongoDBDriverManager')) {
                throw new Exception('require mongodb > 1.0');
            }
    
            $this->config = config('mongo');
            if (!empty($config)) {
                $this->config = array_merge($this->config, $config);
            }
    
            if (!isset($this->manager)) {
                $index = mt_rand(0, $this->config['master_num'] - 1);
                $server = $this->config['servers'][$index];
                $this->server = $server;
                $this->manager = new Manager("mongodb://".$server['username'].":".$server['password']."@".$server['host'].":".$server['port']."/".$server['database']);
            }
        }
    
        public function query($table, $filter, $options) {
            $namespace = $this->server['database'].'.'.$table;
    
            $query = new Query($filter, $options);
            $rows = $this->manager->executeQuery($namespace, $query);
    
            $rows->setTypeMap(['root' => 'array', 'document' => 'array', 'array' => 'array']);
            return $rows->toArray();
        }
    
        public function insert($table, $data) {
            $namespace = $this->server['database'].'.'.$table;
    
            $bulk = new BulkWrite();
            $bulk->insert($data);
            $result = $this->manager->executeBulkWrite($namespace, $bulk);
    
            return $result->getInsertedCount();
        }
    
        public function update($table, $filter, $data, $options = []) {
            $namespace = $this->server['database'].'.'.$table;
    
            $bulk = new BulkWrite();
            $bulk->update($filter, $data, $options);
            $result = $this->manager->executeBulkWrite($namespace, $bulk);
    
            return $result->getMatchedCount();
        }
    
        public function delete($table, $filter, $options = []) {
            $namespace = $this->server['database'].'.'.$table;
    
            $bulk = new BulkWrite();
            $bulk->delete($filter, $options);
            $result = $this->manager->executeBulkWrite($namespace, $bulk);
    
            return $result->getDeletedCount();
        }
    
        public function command($cmd) {
            $namespace = $this->server['database'];
            $rows = $this->manager->executeCommand($namespace, $cmd);
            $rows->setTypeMap(['root' => 'array', 'document' => 'array', 'array' => 'array']);
            return $rows->toArray();
        }
    
        function aggregate($table, $pipeline){
            $cmdOption = [
                'aggregate' => $table,
                'pipeline' => $pipeline,
                'cursor' => new stdClass(),
            ];
            $cmd = new Command($cmdOption);
            return $this->command($cmd);
        }
    }
    

    Mongo.php
    <?php
    namespace apputilmongo;
    
    /**
     * Class Db
     * @package think
     * @method Query cache(mixed $key = null , integer $expire = null) static 设置查询缓存
     * @method mixed value(string $field) static 获取某个字段的值
     * @method array column(string $field, string $key = '') static 获取某个列的值
     * @method Query view(mixed $join, mixed $field = null, mixed $on = null, string $type = 'INNER') static 视图查询
     * @method mixed find(mixed $data = null) static 查询单个记录
     * @method mixed select(mixed $data = null) static 查询多个记录
     * @method void commit() static 用于非自动提交状态下面的查询提交
     * @method void rollback() static 事务回滚
     * @method boolean batchQuery(array $sqlArray) static 批处理执行SQL语句
     * @method string getLastInsID($sequence = null) static 获取最近插入的ID
     */
    
    class Mongo
    {
        /**
         * @var Connection[] 数据库连接实例
         */
        private static $instance = [];
    
        public static function connect($config = []) {
    
            if (empty($config)) {
                $config = config('mongo');
            }
    
            $name = md5(serialize($config));
            if (!isset(self::$instance[$name])) {
                self::$instance[$name] = new Connection($config);
            }
    
            return self::$instance[$name];
        }
    
        /**
         * 调用驱动类的方法
         * @access public
         * @param  string $method 方法名
         * @param  array  $params 参数
         * @return mixed
         */
        public static function __callStatic($method, $params)
        {
            return call_user_func_array([self::connect(), $method], $params);
        }
    }

     MyExample.php

    $cmd = [
    	['$match' => ["user_id" => ['$eq' => intval($user_id)]]],
    	['$project' => [
    		"user_id" => 1,
    		"book_author" => 1,
    		"book_sub_type" => ['$filter' => ['input' => '$book_sub_type', 'as' => 'item', 'cond' => ['$eq' => ['$$item.sex', intval($sex)]]]],
    		"book_type" => ['$filter' => ['input' => '$book_type', 'as' => 'item', 'cond' => ['$eq' => ['$$item.sex', intval($sex)]]]],
    	]],
    	['$project' => [
    		"user_id" => 1,
    		"book_author" => ['$slice' => ['$book_author', $tag_author_size]],
    		"book_sub_type" => ['$slice' => ['$book_sub_type', $tag_size]],
    		"book_type" => ['$slice' => ['$book_type', $tag_size]],
    	]],
    ];
    $tags = Mongo::connect()->aggregate('user_tags', $cmd);
    

      

  • 相关阅读:
    mysql基础(三)存储引擎和锁
    为给定字符串生成MD5指纹
    区块链基本原理,Part-2:工作量证明和权益证明
    区块链基本原理,Part-1:拜占庭容错
    区块链挖矿 2.0
    以太坊 2.0 中的验证者经济模型,Part-2
    以太坊 2.0 中的验证者经济模型,Part-1
    Java归并排序之递归
    Python爬虫入门教程 64-100 反爬教科书级别的网站-汽车之家,字体反爬之二
    Java棋盘覆盖问题
  • 原文地址:https://www.cnblogs.com/werben/p/11713818.html
Copyright © 2020-2023  润新知