Skip to content

ienaga/RedisPlugin

Repository files navigation

RedisPlugin for Phalcon (The correspondence of MySQL sharding.)

Build Status

Latest Stable Version Total Downloads Latest Unstable Version License

Composer

{
    "require": {
       "ienaga/phalcon-redis-plugin": "3.*"
    }
}

Version

PHP: 7.0.x, 7.1.x, 7.2.x
Phalcon: 3.x

phpredis and YAML

sudo yum install libyaml libyaml-devel php-pecl-yaml php-pecl-redis

app/config/config.php

$loader = new Phalcon\Config\Adapter\Yaml\Loader();
return $loader
    ->setIgnore(["routing"]) // ignore yml names
    ->setEnvironment("stg") // default dev
    ->setBasePath(realpath(dirname(__FILE__) . "/../.."))
    ->load();

app/config/database.yml

prd:
stg:
dev:
  database:
    dbAdminMaster:
      adapter:  Mysql
      host:     127.0.0.1
      port:     3301
      username: root
      password: XXXXX
      dbname:   admin
      charset:  utf8
      transaction: true
    dbAdminSlave:
      adapter:  Mysql
      host:     127.0.0.1
      port:     3311
      username: root
      password: XXXXX
      dbname:   admin
      charset:  utf8
      transaction: false
    dbCommonMaster:
      adapter:  Mysql
      host:     127.0.0.1
      port:     3301
      username: root
      password: XXXXX
      dbname:   common
      charset:  utf8
      transaction: false
    dbCommonSlave:
      adapter:  Mysql
      host:     127.0.0.1
      port:     3311
      username: root
      password: XXXXX
      dbname:   common
      charset:  utf8
      transaction: false
    dbUser1Master:
      adapter:  Mysql
      host:     127.0.0.1
      port:     3306
      username: root
      password: XXXXX
      dbname:   user
      charset:  utf8
      transaction: true
    dbUser1Slave:
      adapter:  Mysql
      host:     127.0.0.1
      port:     3316
      username: root
      password: XXXXX
      dbname:   user
      charset:  utf8
      transaction: false
    dbUser2Master:
      adapter:  Mysql
      host:     127.0.0.1
      port:     3307
      username: root
      password: XXXXX
      dbname:   user
      charset:  utf8
      transaction: true
    dbUser2Slave:
      adapter:  Mysql
      host:     127.0.0.1
      port:     3317
      username: root
      password: XXXXX
      dbname:   user
      charset:  utf8
      transaction: false

app/config/redis.yml

prd:
stg:
dev:
  redis:
    # log出力
    logger:
      logging: true # logging ON OFF
      output:  /var/www/project/log/sql.log # output log file path
      
    enabled:   true # false => cache off
    autoIndex: true # false => auto index off

    # 対象のカラムがModelに存在したら使用。上から順に優先。存在が確認できた時点でbreak
    prefix:
      columns:  # e.g. user_id, id, social_id, [account, password]
        - user_id
        - social_id
        - [account, password]
        - id

    # 共通のマスタがあれば登録「table_」と共有部分だけの記載はtable_*と同義
    # common
    common:
      enabled: false
      service:
        name: dbCommon

      dbs: # e.g.  master_, access_log
        - mst_

    # Sharding設定
    shard:
      enabled: true # Shardingを使用しない時はfalse

    # Shardingのマスタ設定
    admin:
      service:
        name: dbAdmin
        
    # Shardingのマスタ設定
    admin:
      service:
        name: dbAdmin
      # ユーザマスタ
      # e.g.
      #    CREATE TABLE IF NOT EXISTS `admin_user` (
      #      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      #      `social_id` varchar(255) NOT NULL,
      #      `admin_db_config_id` int(10) unsigned NOT NULL,
      #      PRIMARY KEY (`id`)
      #    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
      model: AdminUser # e.g. AdminUser or namespace \Project\AdminUser
      column: admin_db_config_id # e.g. admin_db_config_id

      # ユーザマスタの登録「table_」と共有部分だけの記載はtable_*と同義
      dbs: # e.g. admin_, user_ranking
        - admin_
        
      # Shardingをコントロールするテーブルとカラム
      #
      # e.g.
      #    CREATE TABLE IF NOT EXISTS `admin_db_config` (
      #      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      #      `name` varchar(50) NOT NULL,
      #      `gravity` tinyint(3) unsigned NOT NULL DEFAULT '0',
      #      PRIMARY KEY (`id`)
      #    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
      #    INSERT INTO `admin_db_config` (`id`, `name`, `gravity`) VALUES
      #    (1, 'dbUser1', 50),
      #    (2, 'dbUser2', 50);
      # shard config master
      control:
        model: AdminDbConfig # e.g. AdminConfigDb or namespace \Project\AdminConfigDb
        column: name # e.g. name

    # schemaをキャッシュ
    metadata:
      host:   127.0.0.1
      port:   6379
      select: 0
      
    # servers
    server:
      dbMaster:
        host: 127.0.0.1
        port: 6379
        select: 0 # redis select [データベースインデックス]
      dbSlave:
        host: 127.0.0.1
        port: 6379
        select: 0
      dbCommonMaster:
        host: 127.0.0.1
        port: 6379
        select: 0
      dbCommonSlave:
        host: 127.0.0.1
        port: 6379
        select: 0
      dbUser1Master:
        host: 127.0.0.1
        port: 6379
        select: 0
      dbUser1Slave:
        host: 127.0.0.1
        port: 6379
        select: 0
      dbUser2Master:
        host: 127.0.0.1
        port: 6379
        select: 0
      dbUser2Slave:
        host: 127.0.0.1
        port: 6379
        select: 0

app/config/services.php

/**
 * Database connection is created based in the parameters defined in the configuration file
 */
$dbService = new \Phalcon\Mvc\Model\Adapter\Redis\Service();
$dbService->registration();

/**
 * If the configuration specify the use of metadata adapter use it or use memory otherwise
 */
$di->setShared('modelsMetadata', function () {
    return new \Phalcon\Mvc\Model\Adapter\Redis\Metadata\Redis(
        $this->getConfig()
            ->get("redis")
            ->get("metadata")
            ->toArray()
    );
});

findFirst

class Robot extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

# findFirst
$robot = Robot::criteria()
    ->add('id', $id)
    ->add('type', $type, Criteria::NOT_EQUAL)
    ->group('type')
    ->findFirst();

find

class Robot extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

$robot = Robot::criteria()
    ->add('id', array($id), Criteria::IN)
    ->add('type', array($start, $end), Criteria::BETWEEN)
    ->limit(10, 5) // limit, offset
    ->order('type DESC')
    ->find();

cache Control

class Robot extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

$robot = Robot::criteria()
    ->add('id', array($id), Criteria::IN)
    ->add('type', array($start, $end), Criteria::BETWEEN)
    ->limit(10, 30)
    ->order('type DESC')
    ->cache(false)
    ->find();

autoIndex Control

class Robot extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

$robot = Robot::criteria()
    ->add('id', array($id), Criteria::IN)
    ->add('type', array($start, $end), Criteria::BETWEEN)
    ->limit(10, 30)
    ->order('type DESC')
    ->autoIndex(false)
    ->find();

save

class UserItem extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

$userItem = new UserItem();
$userItem->setId($id);
$userItem->setType($type);
$userItem->save();

update

class Robot extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

Robot::criteria()
    ->add("user_status", 1)
    ->add("power", 100)
    ->set("status", 2)
    ->set("name", "robot")
    ->update();
UPDATE `robot` SET `status` = 2, `name` = "robot" WHERE `user_status` = 1 AND `power` = 100;

delete

class Robot extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

Robot::criteria()
    ->add("user_status", 1)
    ->add("power", 100, Robot::GREATER_EQUAL)
    ->delete();
DELETE FROM `robot` WHERE `user_status` = 1 AND `power` >= 100;

count

class Robot extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

$count = Robot::criteria()
    ->add("user_status", 1)
    ->add("power", 100)
    ->add("status", 2)
    ->count();

sum

class Robot extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

$sum = Robot::criteria()
    ->add("user_status", 1)
    ->sum("price");

autoIndex

e.g. PRIMARY = type, INDEX = id, status ※autoIndexをtrueにする事で、PRIMARYもしくはINDEXに一番マッチするクエリに並び替えて発行。

class Robot extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

$robot = Robot::criteria()
    ->limit(10)
    ->add("type", $type)
    ->addGroup("type")
    ->addOrder("id", "DESC")
    ->add("status", $status)
    ->add("id", $id)
    ->find();
SELECT * FROM `robot` 
WHERE `id` = :id: 
AND `type` = :type:
AND `status` = :status: 
GROUP BY `type`
ORDER BY `id` DESC
LIMIT 10

Index Test Mode

テストモードをtrueにしてSQLを発行。 どのIndexにもマッチしない時はErrorを出力。

  • 単体
class Robot extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

$robot = Robot::criteria()
    ->limit(10)
    ->add("type", $type)
    ->addGroup("type")
    ->addOrder("id", "DESC")
    ->add("status", $status)
    ->add("id", $id)
    ->test(true)
    ->find();
  • 全体
class Robot extends \Phalcon\Mvc\Model\Adapter\Redis\Model {}

\RedisPlugin\Mvc\Model::test(true);

$robot = Robot::criteria()
    ->limit(10)
    ->add("type", $type)
    ->addGroup("type")
    ->addOrder("id", "DESC")
    ->add("status", $status)
    ->add("id", $id)
    ->find();