Wake Me Up When September Ends.

A wanderer capable of grasping the beauty of the grass, with a heart full of ancient charm, and a fondness for playful wit. Those who understand my words are knowledgeable individuals; those who decipher my code truly comprehend the essence. I am a wandering code swordsman, carrying my skills and riding freely through the digital world.

时常记不住定时任务一些配置规则,所以这边记录一下!☘

Cron 定时任务是一种在 Unix/Linux 系统中用于执行预定时间间隔的任务的机制。它使用 cron 表达式来定义任务的执行时间。

Cron 表达式由空格分隔的五个字段组成,分别表示分钟、小时、日期、月份和星期几。每个字段可以接受不同的取值范围和特殊字符。

minute   hour   day   month   week   command     顺序:分 时 日 月 周

以下是每个字段的取值范围和特殊字符的说明:

分钟字段:取值范围是 0-59。

小时字段:取值范围是 0-23。

日期字段:取值范围是 1-31。

月份字段:取值范围是 1-12。

星期字段:取值范围是 0-7,其中 0 和 7 都表示星期日。

对于每个字段,可以使用以下特殊字符来定义更复杂的定时任务:

星号(*):表示匹配该字段的所有可能值。

逗号(,):用于分隔多个取值,表示匹配任意一个取值。

连字符(-):用于指定一个范围,表示匹配该范围内的所有值。

斜杠(/):用于指定一个步长,表示匹配该步长的所有值。

以下是一些常见的 cron 表达式示例:

  1. 0 0 * * *:每天的 00:00 执行一次任务。
  2. 0 12 * * 1-5:周一至周五的 12:00 执行一次任务。
  3. 0 0 1 * *:每个月的第一天的 00:00 执行一次任务。
  4. 0 */2 * * *:每隔两个小时执行一次任务。

Cron 定时任务是一种非常灵活和强大的调度机制,可以帮助自动化执行定期任务,例如备份、清理、数据同步等。

工厂模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。

需求的场景

这种模式在面试中经常会被问到,很多面试题的答案会表示该模式经常用于框架的db或cache组件设计。

假设你所在项目组在开发某个项目中,使用了多种缓存数据源,比如有内存,redis,本地文件。目前每次根据不同场景使用不同类型缓存,需要实例化不同缓存实例进行操作,比较繁琐。项目组开发人员希望统一调用缓存入口,简化缓存调用心智负担。

如何解决

  1. 定义cache工厂类(父类)和依赖类
  2. 编写各个类型cache子类
  3. cache工厂类创建调用

实现

这边实现使用PHP代码作为演示,其他oop语言逻辑类似。

😼1.定义cache工厂类(父类)和依赖类

// config 配置类 用于缓存实例化依赖配置数据
class Config
{
    private string $host; //连接host

    private string $dbName;// 数据库名称

    private string $password;// 密码

    private string $userName;// 用户名

    private int $port; //端口

    public function getHost(): string
    {
        return $this->host;
    }

    public function setHost(string $host): static
    {
        $this->host = $host;
        return $this; 
    }

    public function getDbName(): string
    {
        return $this->dbName;
    }

    public function setDbName(string $dbName): static
    {
        $this->dbName = $dbName;
        return $this;
    }

    public function getPassword(): string
    {
        return $this->password;
    }

    public function setPassword(string $password): static
    {
        $this->password = $password;
        return $this;
    }

    public function getUserName(): string
    {
        return $this->userName;
    }

    public function setUserName(string $userName): static
    {
        $this->userName = $userName;
        return $this;
    }
    
    
    public function getPort(): string
    {
        return $this->port;
    }

    public function setPort(int $port): static
    {
        $this->port = $port;
        return $this;
    }
}

// 工厂类

class Cache
{
    protected  Config $config;

    public function __construct(Config $config)
    {
        //通过构造注入Config依赖
        $this->config = $config;
    }

    public static create(string $cache) 
    {
        //创建实例
        return   new $cache($this->config);
    }

    
}

😸2.编写各个类型cache子类

// redis 
class Redis extends Cache
{

    private Redis $redis

    public function __construct(Config $config)
    {
        parent::__construct(Config $config);

        $this->connect()
    }

    protected function connect()
    {
        //根据Config进行缓存连接
        $this->redis = new \Redis();

        // 连接 Redis 服务器
        $this->redis->connect($this->config->getHost() , $this->config->getPort() ??  6379);

        // 可选:设置 Redis 密码
        $this->redis->auth($this->config->getPassword());

    }

    // 动态调用redis 方法
    public function __call($method, ...$arguments) {
        call_user_func([$this->redis, $method], ...$arguments);
    }


}

//内存
class Memory extends Cache
{

    public function __construct(Config $config)
    {
        
        parent::__construct(Config $config);
        
    }

   
}

//文件
class File extends Cache
{

    private string $cachePath = '/dev/logs/'

    public function __construct(Config $config)
    {
         parent::__construct(Config $config);

    }

   
}

😺3.cache工厂类创建调用

class  Demo
{
    public  function  run()
    {
        $config = (new Config())->setHost('localhost')
        ->setUserName('demo')
        ->setPassword('*****');

        $cache = new Cache($config);
        //创建redis cache实例
        $redis = $cache->create(Redis::class);
        //创建本地file cache实例
        $file = $cache->create(File::class);
    }
}

一些特殊部署场景下,需要指定某个容器ip以便于访问。可以使用Docker的网络模式来间接地控制容器的IP地址,所以这边记录一下!☘

自定义一个名为my-docker-net网络

docker network create --subnet=172.0.0.0/24 my-docker-net

指定容器网络并设置固定ip

docker run -d   --net=my-docker-net --ip=172.0.0.3 --name=[容器名字] -v [镜像名字]

通过IP172.0.0.3访问该容器了。

补充知识

172.0.0.0/24 是一个 CIDR(Classless Inter-Domain Routing)表示法,它使用网络地址和掩码长度来表示一个 IP 地址范围。255.255.255.0 是对应的子网掩码,也称为网络掩码。包含了从 172.0.0.0 到 172.0.0.255 的所有 IP 地址。

在 CIDR(Classless Inter-Domain Routing)表示法中,斜线后的数字表示掩码长度,用于指示网络地址中的连续前缀位数。

具体来说,掩码长度是指网络地址中左边的连续位数,用于表示网络部分。剩余的位数则用于表示主机部分。

对于 IPv4 地址,掩码长度的有效范围是从 0 到 32。较小的掩码长度表示更大的网络范围,而较大的掩码长度表示更小的网络范围。

例如:

  1. /8 表示网络地址中的前 8 位用于网络部分,后 24 位用于主机部分。
  2. /16 表示网络地址中的前 16 位用于网络部分,后 16 位用于主机部分。
  3. /24 表示网络地址中的前 24 位用于网络部分,后 8 位用于主机部分。

因此,/8 中的数字 8 表示网络地址中的前 8 位用于网络部分,剩下的位用于主机部分。这意味着 172.0.0.0/8 表示一个非常大的网络范围,其中 172.0.0.0 到 172.255.255.255 都属于同一个网络。

有时候遇到批量删除很多数据表的时候,一个一个去删除太麻烦。使用如下sql可以根据则匹配,进行批量删除数据表!

注意删除数据表是很危险的行为,确保你确认所删除数据已经备份或确认无用!!!

跑路删库/表,是违法行为!!!🧟‍♀️

SET @query = '';

SELECT REPLACE(GROUP_CONCAT('DROP TABLE IF EXISTS `', TABLE_NAME, '`;'), ';,', ';') INTO @query
FROM information_schema.tables
WHERE table_schema = 'database_name'
  AND table_name REGEXP 'regex_pattern';
 PREPARE stmt FROM @QUERY;

EXECUTE stmt;

DEALLOCATE PREPARE stmt;

上述代码中的 database_name 替换为要操作的数据库的名称,regex_pattern 替换为要匹配的表名的正则表达式模式。

此脚本将首先使用 SHOW TABLES 语句和 REGEXP 运算符来获取匹配正则表达式模式的表名。然后,它将使用 DROP TABLE 语句生成一个包含所有匹配表名的脚本,并使用 EXECUTE 执行删除操作!

如果想确保万无一失的话,可以使用下面sql进行与生成drop语句预览以便再次确认!

SELECT REPLACE(GROUP_CONCAT('DROP TABLE IF EXISTS `', TABLE_NAME, '`;'), ';,', ';')
FROM information_schema.tables
WHERE table_schema = 'database_name'
  AND table_name REGEXP 'regex_pattern';

🚩 跑路删库/表,是违法行为!!!使用改sql进行违法,本人概不负责!!!