<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-CN"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://www.lidaxiang.cn/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.lidaxiang.cn/" rel="alternate" type="text/html" hreflang="zh-CN" /><updated>2026-11-01T14:58:23+08:00</updated><id>https://www.lidaxiang.cn/feed.xml</id><title type="html">荒岛书生</title><subtitle>程序员，文学、古琴、流行音乐、运动爱好者。</subtitle><author><name>荒岛书生</name><email>lidaxiang0@outlook.com</email></author><entry><title type="html">How to Imporve coding skills</title><link href="https://www.lidaxiang.cn/codingskils/improve-coding-use-conditionals" rel="alternate" type="text/html" title="How to Imporve coding skills" /><published>2020-09-20T00:00:00+08:00</published><updated>2020-09-20T00:00:00+08:00</updated><id>https://www.lidaxiang.cn/codingskils/improve-coding-use-conditionals</id><content type="html" xml:base="https://www.lidaxiang.cn/codingskils/improve-coding-use-conditionals"><![CDATA[<p>总结编程技巧，基本来自于代码大全这本书的读后感和工作里的感悟。</p>

<!---more--->

<h2 id="use-conditionals">Use Conditionals</h2>
<h4 id="if-then-语句">if then 语句</h4>
<ol>
  <li>代码的 正常路径清晰吗</li>
  <li>if-then 测试对“等于号情况”分支的处理方式正确吗</li>
  <li>把正常情况的处理放在 if 后面而不要放在 else 后面。</li>
  <li>让 if 条件里不要空着，可以简单把条件做一个否定操作，这样就能把 else 的内容移到 if 里面。</li>
  <li>如果不需要 else 情况，也请在空的 else 语句里，写上注释说明为什么不需要 else。</li>
  <li>记得测试 else 子句的正确性。</li>
  <li>检查 if 和 else 的子句是不是弄反了，if里代码是正常情况走的，else一般是用来处理错误、异常、例外情况的。</li>
</ol>

<h4 id="if-then-else">if-then-else</h4>
<ol>
  <li>当出现多个 if 、else if、else if 连起来实现 switch case 效果的时候，请注意把复杂的 if判断条件 抽象成一个布尔函数，利用布尔函数掉调用简化复杂的检测。</li>
  <li>把最常见的情况放在最前面的if</li>
  <li>确保所有情况都被考虑到，最后的else是为了提示程序员而记录 exception 的。</li>
  <li>如果你的语言支持，请把 if-then-else 语句串替换成switch case，更易于理解。</li>
</ol>

<h4 id="case-statements">case statements</h4>
<p>case 语句或者 swich 语句在不同 code language 里有很大差异。如何有效使用，有些共同原则。</p>

<ol>
  <li>选择最有效的排列：把正常的情况排在前面，把执行频率高的排在前面，如果重要性相同按照开头字母顺序或者数字顺序排列。</li>
  <li>简化没冲情况对应的操作，每种情况相关的代码应该短小精悍，如果特别复杂则建议写到函数里。</li>
  <li>不要为了使用case，而刻意去截取字符串之类的。也就是说函数输入与case 变量要完全对应，如果函数输入了字符串，而case 只支持char和数字，那就不要用case 而转用if else。</li>
  <li>把default 语句只用于检查真正的默认情况，而不要把最后一种剩余情况用default处理（这样会让程序丧失处理错误的能力以及失去利用case代码自动说明功能的能力）。这种用法需要在所有case之前检测输入变量的正确性。</li>
  <li>利用default子句检查错误情况</li>
  <li>在C++和java里，避免带阿玛执行越过一条case子句的末尾，加上break。</li>
</ol>

<h2 id="controlling-loops">Controlling Loops</h2>
<p>不同类型循环的差异主要体现在灵活度和检查位置上，包括循环次数的多少、循环是否需要至少执行一次、检查循环是否执行完备的位置在开始、中间或结尾。</p>
<h4 id="选择循环的种类">选择循环的种类</h4>
<ol>
  <li>counted loop执行次数是一定的</li>
  <li>连续求值的循环，预先不知道将要执行多少次，每次迭代时都要检测是否应该结束。</li>
  <li>无限循环，一旦启动就会一直执行下去，例如微波炉、导航仪、心脏起搏器。</li>
  <li>迭代器循环 iterator loop，对容器类里面的每个元素执行一次操作。</li>
  <li>如果你不知道循环要迭代 多少次，那么可以使用while 循环。</li>
  <li></li>
</ol>

<h4 id="循环控制">循环控制</h4>

<h4 id="轻松创建循环">轻松创建循环</h4>

<h4 id="循环和数组的关系">循环和数组的关系</h4>]]></content><author><name>荒岛书生</name><email>lidaxiang0@outlook.com</email></author><category term="codingSkils" /><category term="work" /><category term="coding" /><category term="skills" /><summary type="html"><![CDATA[总结编程技巧，基本来自于代码大全这本书的读后感和工作里的感悟。]]></summary></entry><entry><title type="html">How to Use Grafana(For monitor or dashboad)</title><link href="https://www.lidaxiang.cn/architecture/how-to-use-grafana" rel="alternate" type="text/html" title="How to Use Grafana(For monitor or dashboad)" /><published>2020-09-13T00:00:00+08:00</published><updated>2020-09-13T00:00:00+08:00</updated><id>https://www.lidaxiang.cn/architecture/how-to-use-grafana</id><content type="html" xml:base="https://www.lidaxiang.cn/architecture/how-to-use-grafana"><![CDATA[<p>Grafana 是一个可视化工具，支持 MySQL、Prometheus等多种类型的数据库，对时序数据库更友好。它的作用在于能够快速将查询结果展示出来，支持的图表类型包括不限于折线图、饼图(插件)、条状图、表格、单一数字等。</p>

<!---more--->

<p>Grafana 官方地址： <a href="https://grafana.com/">https://grafana.com/</a></p>

<h2 id="待补充">待补充</h2>]]></content><author><name>荒岛书生</name><email>lidaxiang0@outlook.com</email></author><category term="architecture" /><category term="work" /><category term="user_permisstion" /><category term="architecture" /><summary type="html"><![CDATA[Grafana 是一个可视化工具，支持 MySQL、Prometheus等多种类型的数据库，对时序数据库更友好。它的作用在于能够快速将查询结果展示出来，支持的图表类型包括不限于折线图、饼图(插件)、条状图、表格、单一数字等。]]></summary></entry><entry><title type="html">How to Use Docker to create Django ENV</title><link href="https://www.lidaxiang.cn/architecture/how-to-use-docker-with-django" rel="alternate" type="text/html" title="How to Use Docker to create Django ENV" /><published>2020-09-12T00:00:00+08:00</published><updated>2020-09-12T00:00:00+08:00</updated><id>https://www.lidaxiang.cn/architecture/how-to-use-docker-with-django</id><content type="html" xml:base="https://www.lidaxiang.cn/architecture/how-to-use-docker-with-django"><![CDATA[<p>Grafana 是一个可视化工具，支持 MySQL、Prometheus等多种类型的数据库，对时序数据库更友好。它的作用在于能够快速将查询结果展示出来，支持的图表类型包括不限于折线图、饼图(插件)、条状图、表格、单一数字等。</p>

<!---more--->

<p>Grafana 官方地址： <a href="https://grafana.com/">https://grafana.com/</a></p>

<h2 id="待补充">待补充</h2>]]></content><author><name>荒岛书生</name><email>lidaxiang0@outlook.com</email></author><category term="architecture" /><category term="work" /><category term="user_permisstion" /><category term="architecture" /><summary type="html"><![CDATA[Grafana 是一个可视化工具，支持 MySQL、Prometheus等多种类型的数据库，对时序数据库更友好。它的作用在于能够快速将查询结果展示出来，支持的图表类型包括不限于折线图、饼图(插件)、条状图、表格、单一数字等。]]></summary></entry><entry><title type="html">Centos firewalld service</title><link href="https://www.lidaxiang.cn/live/firewalld-centos" rel="alternate" type="text/html" title="Centos firewalld service" /><published>2020-07-18T00:00:00+08:00</published><updated>2020-07-18T00:00:00+08:00</updated><id>https://www.lidaxiang.cn/live/firewalld-centos</id><content type="html" xml:base="https://www.lidaxiang.cn/live/firewalld-centos"><![CDATA[<p>Centos firewalld service
<!---more---></p>

<h2 id="开放端口">开放端口</h2>
<p>永久的开放需要的端口</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//Enable firewall
systemctl enable firewalld
systemctl start firewalld
systemctl status firewalld

sudo firewall-cmd --zone=public --add-port=3000/tcp --permanent
sudo firewall-cmd --reload

// 之后检查新的防火墙规则
firewall-cmd --list-all
</code></pre></div></div>

<h2 id="关闭防火墙">关闭防火墙</h2>
<p>由于只是用于开发环境，所以打算把防火墙关闭掉</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//临时关闭防火墙,重启后会重新自动打开
systemctl restart firewalld


//Disable firewall
systemctl disable firewalld
systemctl stop firewalld
systemctl status firewalld
</code></pre></div></div>

<h2 id="检查防火墙状态">检查防火墙状态</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>firewall-cmd --state
firewall-cmd --list-all
</code></pre></div></div>]]></content><author><name>荒岛书生</name><email>lidaxiang0@outlook.com</email></author><category term="live" /><category term="work" /><category term="centos" /><category term="firewalld" /><summary type="html"><![CDATA[Centos firewalld service]]></summary></entry><entry><title type="html">漫谈 prometheus</title><link href="https://www.lidaxiang.cn/architecture/prometheus" rel="alternate" type="text/html" title="漫谈 prometheus" /><published>2020-06-20T00:00:00+08:00</published><updated>2020-06-20T00:00:00+08:00</updated><id>https://www.lidaxiang.cn/architecture/prometheus</id><content type="html" xml:base="https://www.lidaxiang.cn/architecture/prometheus"><![CDATA[<p>以下应用是基于 Springboot 项目的监控，如果是 Springboot 2 版本，可以安装 mircrometer 组件来提供对 prometheus 的支持。
<!---more---></p>

<p>prometheus 官方地址： https://prometheus.io/</p>

<h2 id="can-use-4-kinds-of-metrics">Can use 4 kinds of metrics</h2>
<p>Prometheus 中提供了四种指标类型（参考：Prometheus 的指标类型），Counter、Timer、 以及直方图（Histogram）和摘要（Summary），后两者是最复杂和难以理解的.</p>

<p>例如Histogram 会在一段时间范围内对数据进行采样（通常是请求持续时间或响应大小等），并将其计入可配置的存储桶（bucket）。</p>

<h2 id="prometheus-commands-exampls">Prometheus Commands Exampls</h2>
<p>以下命令更适合与 Grafana 搭配使用。</p>

<p>Sub-Interface QPS (rate 10s, status=200)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rate(http_server_requests_seconds_count{application="PROJECT", uri!="/actuator/prometheus" ,status="200"}[1m]) 
</code></pre></div></div>

<p>Sub-Interface Latency P90 (rate 1min , seconds)
‘’’
 histogram_quantile(0.9, sum(rate(http_server_requests_seconds_bucket{application=”PROJECT_NAME”, uri!=”/actuator/prometheus”}[1m])) by (uri, le)) 
‘’’</p>

<p>Sub-Interface Latency P50 (rate 1min , seconds)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> histogram_quantile(0.5, sum(rate(http_server_requests_seconds_bucket{application="PROJECT_NAME", uri!="/actuator/prometheus"}[1m])) by ( uri, le)) 
</code></pre></div></div>

<p>TOP URL Visits</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> topk(10, sum( http_server_requests_seconds_count{application="PROJECT_NAME",uri!="/actuator/prometheus"}) by (uri))
</code></pre></div></div>

<p>HTTP methods Count</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  sum(http_server_requests_seconds_count {application="PROJECT_NAME", uri!="/actuator/prometheus"}) by (status)
</code></pre></div></div>

<p>Log Count By Level</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>topk(5,  sum(logback_events_total{application="PROJECT_NAME"}) by (level))
</code></pre></div></div>]]></content><author><name>荒岛书生</name><email>lidaxiang0@outlook.com</email></author><category term="architecture" /><category term="work" /><category term="user_permisstion" /><category term="architecture" /><summary type="html"><![CDATA[以下应用是基于 Springboot 项目的监控，如果是 Springboot 2 版本，可以安装 mircrometer 组件来提供对 prometheus 的支持。]]></summary></entry><entry><title type="html">漫谈架构技术</title><link href="https://www.lidaxiang.cn/architecture/anyinfo-java" rel="alternate" type="text/html" title="漫谈架构技术" /><published>2020-03-30T00:00:00+08:00</published><updated>2020-03-30T00:00:00+08:00</updated><id>https://www.lidaxiang.cn/architecture/anyinfo-java</id><content type="html" xml:base="https://www.lidaxiang.cn/architecture/anyinfo-java"><![CDATA[<p>本文介绍技术选型原则、高可用如何做、一般商业应用的数据库配置、电商场景里的超卖如何处理等零散知识点，点到为止。</p>

<!---more--->

<h2 id="高并发高可用高性能">高并发，高可用，高性能</h2>
<h4 id="软件工程方面">软件工程方面</h4>
<ol>
  <li>事前：多机服务冗余、隔离、自动发布、灰度发布、数据库加索引、集成测试 &amp; 单元测试</li>
  <li>中间：多级缓存（业务，sql缓存，中间件），离线，重试i，限流降级，异步，监控，回滚策略</li>
  <li>事后：复盘，优化迭代</li>
</ol>

<h4 id="编程技巧">编程技巧</h4>
<ol>
  <li>不要在for循环里查询数据库，造成过多查询</li>
  <li>重要的日志要区分error、info、debug 记录下来</li>
  <li>调用第三方服务要考虑好服务重试问题</li>
  <li>严格命名参数、方法名、类名，这将在后来给你大大节约回想代码的时间</li>
  <li>强烈建议加注释，即便其他人都不写。除非你的记忆里能记得起来几个月之前的代码是什么意思。</li>
  <li><strong>保持类、方法只要有单一职责</strong>。所以要多拆分，不要写一个100行的方法，让别人很难迅速理解！如何拆分设计各个类、类的方法，这是一件入门容易学成难的事情！</li>
</ol>

<h2 id="技术选型原则">技术选型原则：</h2>
<p>越合适越好，越简单越好。多使用第三方库。</p>

<h4 id="编程语言">编程语言</h4>
<p>想要用最少的人力时间开发，选Python 。
想要最容易找到员工，选Java。
想要跟随潮流，2020年比较流行的、个人比较看好 Golang、Ruby。</p>

<h4 id="数据库选型">数据库选型</h4>
<p>tidb：不会有join、事务问题。
crdb： 搭建复杂，对性能配置要求高</p>

<h4 id="数据仓库流计算">数据仓库&amp;流计算</h4>
<p>olap
doris
sparksql presto impala  druid  flink</p>

<h2 id="一般商业应用的数据库配置">一般商业应用的数据库配置</h2>
<p>数据库连接池大小  一般配置 100左右，针对4核CPU、10，能支持7k的并发量。
druid 连接池</p>

<p>分布式存储：
mysql  NoSQL   NewSQL   olap
MySQL： 分表  500w，2G大小；index  pool  buffer  size
tidb：</p>

<h2 id="场景一超卖">场景一：超卖</h2>
<p>超卖是商业 to C 的系统里常碰到的问题，要想解决这个问题，需要设计高可用、高并发、高性能、高拓展等多个方面。</p>

<ol>
  <li>服务重试
    <ol>
      <li>A–B；</li>
      <li>竞争</li>
    </ol>
  </li>
  <li>
    <p>redis 解决：<br />
 分布式锁：lua+key+自动失效；
          redis ，spring interation</p>

    <p>分段锁： K1,K2，Kn重试 ；随机负载</p>

    <p>mysql 解决<br />
     1. 悲观锁，select * from where user for update  排它锁<br />
     2. 乐观锁
         1. mvcc，业务检查
         2. case when ，update set case when then 下单</p>
  </li>
  <li>过滤器、拦截器
使用过滤器拦截器、提前分流，提前预先判断错误并返回客户端，尽量在代码层解决错误产生，尽量避免错误的请求落在数据库里。比如提前判断请求参数的范围、提前在redis里缓存商品 SKU 避免无效的 SKU 查询等。</li>
</ol>]]></content><author><name>荒岛书生</name><email>lidaxiang0@outlook.com</email></author><category term="architecture" /><category term="work" /><category term="user_permisstion" /><category term="architecture" /><summary type="html"><![CDATA[本文介绍技术选型原则、高可用如何做、一般商业应用的数据库配置、电商场景里的超卖如何处理等零散知识点，点到为止。]]></summary></entry><entry><title type="html">Solutions about MySQL Distributed</title><link href="https://www.lidaxiang.cn/architecture/mysql-distributed" rel="alternate" type="text/html" title="Solutions about MySQL Distributed" /><published>2019-12-21T00:00:00+08:00</published><updated>2019-12-21T00:00:00+08:00</updated><id>https://www.lidaxiang.cn/architecture/mysql-distributed</id><content type="html" xml:base="https://www.lidaxiang.cn/architecture/mysql-distributed"><![CDATA[<p>MySQL 主从复制、备份复制以及分布式集群的方案。
<!---more---></p>

<h2 id="1主从复制">1.主从复制</h2>
<p>MySQL 主从复制 比较简单，但需要把已有的 MySQL 服务的 my.cnf 文件修改，再把 slave MySQL 服务的配置文件修改，最后重启两个服务。以下 1.1 ~ 1.4 是在 Django 中具体的用法。</p>

<h4 id="11-配置">1.1 配置</h4>
<p>Django默认的是default,我们按照它的格式直接添加一个新的配置：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>DATABASES = {
 'default': {
 'ENGINE': 'django.db.backends.mysql',
 'HOST': '127.0.0.1', # 主服务器的运行ip
 'PORT': 3306, # 主服务器的运行port
 'USER': 'django', # 主服务器的用户名
 'PASSWORD': 'django', # 主服务器的密码
 'NAME': 'djangobase' # 数据表名
 },
 'slave': {
 'ENGINE': 'django.db.backends.mysql', 
 'HOST': '127.0.0.1',
 'PORT': 8306,
 'USER': 'django_slave',
 'PASSWORD': 'django_slave',
 'NAME': 'djangobase_slave'
 }
}
</code></pre></div></div>

<h4 id="12-手动操作方式">1.2 手动操作方式</h4>
<p>代码里可以直接操控数据库：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> models.User.objects.using('default').create
</code></pre></div></div>
<h4 id="13-自动操控方式">1.3 自动操控方式</h4>
<p>在settings.py中指定DATABASE_ROUTERS</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>DATABASE_ROUTERS = ["app001.db_router.MasterSlaveDBRouter"]
</code></pre></div></div>

<p>并新建 routers.py 文件：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class MasterSlaveDBRouter(object):
 """数据库主从读写分离路由"""
 
 def db_for_read(self, model, **hints):
 """读数据库"""
 return "slave"
 
 def db_for_write(self, model, **hints):
 """写数据库"""
 return "default"
 
 def allow_relation(self, obj1, obj2, **hints):
 """是否运行关联操作"""
 return True　
</code></pre></div></div>

<h4 id="14-存在问题">1.4 存在问题</h4>
<p>主要问题是: 同步延迟。
原因:</p>
<ol>
  <li>慢查询</li>
  <li>大事务同步慢</li>
  <li>Binlog 同步时对 IO 有要求</li>
</ol>

<h2 id="2分布式-mysql-集群----mysql-innodb-cluster">2.分布式 MySQL 集群 -  MySQL InnoDB Cluster</h2>
<h4 id="21--mysql-innodb-cluster">2.1  MySQL InnoDB Cluster</h4>
<p>MySQL 5.7 终于实现了原生的基于InnoDB的集群功能。它由以下三个组件完成:</p>

<h4 id="22-mysql-group-replication">2.2 MySQL Group Replication</h4>
<p>MySQL Group Replication（下简称MGR）准确来说是官方推出的高可用解决方案，基于原生复制技术，并以插件的方式提供。</p>

<p>MySQL 5.7 引入了 Group Replication 功能，可以在一组 MySQL 服务器之间实现自动主机选举，形成一主多从结构。经过高级配置后，可以实现多主多从结构。</p>

<h4 id="23-mysql-router">2.3 MySQL Router</h4>
<p>MySQL Router 是一个轻量级透明中间件，可以自动获取上述集群的状态，规划 SQL 语句，分配到合理的 MySQL 后端进行执行。MySQL Router是InnoDB Cluster（MySQL 7.X）的一部分，MySQL 5.6 等版本数据库仍然可以使用Router作为其中间代理层。MySQL Router是MySQL Proxy的替代方案，MySQL官方不建议将MySQL Proxy用于生产环境。</p>

<p>当下游有多个MySQL Servers，无论主、从，Router可以对读写请求进行负载均衡。当下游某个Server失效时，Router可以将其从Active列表中移除，当其online后再次加入Active列表，即提供了Failover特性。通常建议基于“Agent”方式部署，即将Router与应用部署在机器上。Router通常是解决“MySQL集群规模性迁移”，比如跨机房部署、流量迁移、异构兼容，或者解决MySQL集群规模性宕机时快速切换等。</p>

<h4 id="24-mysql-shell">2.4 MySQL Shell</h4>
<p>MySQL Shell 是一个同时支持 JavaScript 和 SQL 的交互程序，可以快速配置 InnoDB Cluster。</p>

<h4 id="25-admin-api">2.5 Admin API</h4>
<p>Admin API：一个特殊的API通过MySQL Shell使用，可以用于对Innodb Cluster进行配置管理</p>

<h4 id="如何使用上述组建">如何使用上述组建</h4>
<ol>
  <li>准备同一内网下多个mysql环境</li>
  <li>在任一台服务器上启动 mysql-shell</li>
  <li><code class="language-plaintext highlighter-rouge">dba.configureLocalInstance</code> 命令修正 MySQL 配置</li>
  <li>在主节点机器上使用<code class="language-plaintext highlighter-rouge">mysqlsh</code>命令，完成集群创建和子节点添加</li>
  <li>安装 mysqlrouter，使用主节点获取配置，启动 mysqlrouter</li>
  <li>测试请求是否被 SQL Router 负载给后端 MySQL 服务器</li>
</ol>

<h2 id="3-mysql-ndb-cluster">3. MySQL NDB Cluster</h2>
<p>MySQL NDB Cluster 容易与MySQL InnoDB Cluster混淆，是另外一款产品，提供更高级别的可用性和冗余性。适用于分布式计算环境，使用内存型的NDB存储引擎。</p>

<h2 id="refrences">Refrences</h2>
<p><a href="https://blog.csdn.net/wzy0623/article/details/81103469">使用MySQL Router实现高可用、负载均衡、读写分离</a>
<a href="https://zhuanlan.zhihu.com/p/31311700">如何使用 MySQL 5.7 内置的 InnoDB 集群</a>
<a href="https://www.zhihu.com/question/53617036/answer/135776740">如何看待MySQL发布的Group Replication</a>
<a href="https://zhuanlan.zhihu.com/p/84214079">Django连接多个数据库并实现读写分离</a>
<a href="https://www.modb.pro/db/13606">MySQL InnoDB Cluster 详解</a></p>]]></content><author><name>荒岛书生</name><email>lidaxiang0@outlook.com</email></author><category term="architecture" /><category term="work" /><category term="mysql" /><category term="distributed" /><summary type="html"><![CDATA[MySQL 主从复制、备份复制以及分布式集群的方案。]]></summary></entry><entry><title type="html">100 Questions about MySQL</title><link href="https://www.lidaxiang.cn/architecture/hundred-mysql-question" rel="alternate" type="text/html" title="100 Questions about MySQL" /><published>2019-11-07T00:00:00+08:00</published><updated>2019-11-07T00:00:00+08:00</updated><id>https://www.lidaxiang.cn/architecture/hundred-mysql-question</id><content type="html" xml:base="https://www.lidaxiang.cn/architecture/hundred-mysql-question"><![CDATA[<p>记录一些常见的 MySQL 问题。
<!---more---></p>

<h3 id="1-mysql-存储引擎及其优点">1. MySQL 存储引擎及其优点</h3>
<p>MyiSAM</p>

<h2 id="2-查看系统正在运营的mysql语句">2. 查看系统正在运营的MySQL语句</h2>
<p><code class="language-plaintext highlighter-rouge">show processlist</code> 命令
SHOW PROCESSLIST显示哪些线程正在运行。您也可以使用mysqladmin processlist语句得到此信息。
各列的含义和用途：
ID列：一个标识，你要kill一个语句的时候很有用，用命令杀掉此查询 /*/mysqladmin kill 进程号。</p>

<p>user列：显示单前用户，如果不是root，这个命令就只显示你权限范围内的sql语句。</p>

<p>host列：显示这个语句是从哪个ip的哪个端口上发出的。用于追踪出问题语句的用户。</p>

<p>db列：显示这个进程目前连接的是哪个数据库。</p>

<p>command列：显示当前连接的执行的命令，一般就是休眠（sleep），查询（query），连接（connect）。</p>

<p>time列：此这个状态持续的时间，单位是秒。</p>

<p>state列：显示使用当前连接的sql语句的状态，很重要的列，后续会有所有的状态的描述，请注意，state只是语句执行中的某一个状态，一个 sql语句，以查询为例，可能需要经过copying to tmp table，Sorting result，Sending data等状态才可以完成</p>

<p>info列：显示这个sql语句，因为长度有限，所以长的sql语句就显示不全，但是一个判断问题语句的重要依据。</p>

<h3 id="3-如何查看slowsql">3. 如何查看slowsql</h3>
<h4 id="方法一全局变量设置">方法一：全局变量设置</h4>
<p>将 slow_query_log 全局变量设置为“ON”状态</p>

<p>mysql&gt; set global slow_query_log=’ON’; 
设置慢查询日志存放的位置</p>

<p>mysql&gt; set global slow_query_log_file=’/usr/local/mysql/data/slow.log’;
查询超过1秒就记录</p>

<p>mysql&gt; set global long_query_time=1;</p>
<h4 id="方法二配置文件设置">方法二：配置文件设置</h4>
<p>修改配置文件my.cnf，在[mysqld]下的下方加入</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[mysqld]
slow_query_log = ON
slow_query_log_file = /usr/local/mysql/data/slow.log
long_query_time = 1
</code></pre></div></div>

<p>重启MySQL服务: service mysqld restart</p>

<p>查看是否成功：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mysql&gt; show variables like 'slow_query%';
mysql&gt; show variables like 'long_query_time%';
</code></pre></div></div>

<p>其他参数解释:</p>
<ol>
  <li>slow_query_log 这个参数设置为ON，可以捕获执行时间超过一定数值的SQL语句。</li>
  <li>long_query_time 当SQL语句执行时间超过此数值时，就会被记录到日志中，建议设置为1或者更短。</li>
  <li>slow_query_log_file 记录日志的文件名。</li>
  <li>log_queries_not_using_indexes  这个参数设置为ON，可以捕获到所有未使用索引的SQL语句，尽管这个SQL语句有可能执行得挺快。</li>
</ol>

<h4 id="测试">测试</h4>
<p>执行<code class="language-plaintext highlighter-rouge">select sleep(2);</code> ，然后使用命令 <code class="language-plaintext highlighter-rouge">cat /usr/local/mysql/data/slow.log</code>查看是否生成慢查询日志.</p>

<h2 id="4-mysql-host-is-blocked-because-of-many-connection-errors-问题the-host_cache-table问题">4. MySql Host is blocked because of many connection errors 问题(The host_cache Table问题)</h2>
<p>原因：　　同一个ip在短时间内产生太多（超过mysql数据库max_connection_errors的最大值）中断的数据库连接而导致的阻塞；</p>

<p>解决办法2种：</p>
<ol>
  <li>进入mysql控制台，执行：flush hosts;</li>
  <li>根治办法：max_connect_errors修改，以及查出引起连接错误的地方</li>
</ol>

<h2 id="5-mysql-性能调优">5. MySQL 性能调优</h2>
<p>可以调优的关键指标包括：</p>
<ol>
  <li>IOPS：Input/Output operation Per Second, 每秒处理的IO请求次数。</li>
  <li>QPS：Query Per Second，每秒请求（查询）次数。这</li>
  <li>
    <p>TPS：Transaction Per Second，每秒事务数。TPS参数MySQL原生没有提供，如果需要我们自己算，可以利用计算的公式：TPS = (Com_commit + Com_rollback) / Seconds
具体内容可以看 <a href="https://juejin.im/entry/59eee654f265da432a7ac432">文章 - Mysql性能调优与测试</a></p>
  </li>
  <li>
    <p>查看 MySQL 版本
若没有连接到 MySQL 服务器，使用 <code class="language-plaintext highlighter-rouge">mysql\bin&gt;mysql -V</code>
若如果已经连接到了MySQL服务器，则运行下面的命令：<code class="language-plaintext highlighter-rouge">mysql&gt; select version();</code></p>
  </li>
  <li>MySQL时间函数 date_sub(), weekday(), curdate()
date_sub
含义: 从日期减去指定的时间间隔.
语法格式: SELECT DATE_SUB(date,INTERVAL expr unit)
案例: select date_sub(curdate(),INTERVAL WEEKDAY(curdate())-26 DAY)</li>
</ol>

<p>日期表示: 年-月-日
时间表示: 年-月-日 时:分:秒</p>

<p>解读:
select curdate();   #获取当前日期
select WEEKDAY(curdate());   #WEEKDAY函数返回一个日期的工作日索引值，即星期一为0，星期二为1，星期日为6。
select WEEKDAY(curdate()) - 26;
select date_sub(‘2020-02-24’, INTERVAL 26 DAY);  #当前日期减去26天的时间
select date_sub(‘2020-02-24’, INTERVAL -26 DAY); #当前日期减去负26天的时间,即加26天</p>

<ol>
  <li>MySQL 查看表占用空间大小
```
1，切换数据库
use information_schema;</li>
</ol>

<p>2，查看数据库使用大小
select concat(round(sum(data_length/1024/1024),2),’MB’) as data from tables where table_schema=’DB_Name’ ;</p>

<p>3，查看表使用大小
select concat(round(sum(data_length/1024/1024),2),’MB’) as data from tables where table_schema=’DB_Name’ and table_name=’Table_Name’;
```</p>

<h2 id="参考文献">参考文献</h2>
<p><a href="https://www.cnblogs.com/luyucheng/p/6265594.html">MySQL慢查询（一） - 开启慢查询</a>
<a href="https://dev.mysql.com/doc/refman/5.6/en/host-cache-table.html">The host_cache Table</a>
<a href="https://blog.csdn.net/qq_21683643/article/details/81003136?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase">MySQL查看表占用空间大小</a></p>]]></content><author><name>荒岛书生</name><email>lidaxiang0@outlook.com</email></author><category term="architecture" /><category term="work" /><category term="mysql" /><summary type="html"><![CDATA[记录一些常见的 MySQL 问题。]]></summary></entry><entry><title type="html">Django experience</title><link href="https://www.lidaxiang.cn/python/experience-django" rel="alternate" type="text/html" title="Django experience" /><published>2018-12-12T00:00:00+08:00</published><updated>2018-12-12T00:00:00+08:00</updated><id>https://www.lidaxiang.cn/python/experience-django</id><content type="html" xml:base="https://www.lidaxiang.cn/python/experience-django"><![CDATA[<p>总结 Django Framework 使用过程中的不常遇到的技巧经验，以备后用。内容包括但不限于 ORM 模型、Static、Templates、Admin 模块等原生 Django 的功能。</p>

<!---more--->
<blockquote>
  <p>StartTime: 2017-03-22,ModifyTime:2018-12-12</p>
</blockquote>

<h2 id="一django-orm">一、Django ORM</h2>
<ol>
  <li>ORM：Object Relational Mapping(关系对象映射)</li>
  <li>ORM 原理：
    <ul>
      <li>Django自带的orm是data_first类型的ORM，使用前必须先创建数据库。</li>
      <li>在django中，根据代码中的类自动生成数据库的表也叫–code first。obj.id  obj.name…..类实例对象的属性</li>
      <li>类名对应——》数据库中的表名</li>
      <li>类属性对应———》数据库里的字段</li>
      <li>类实例对应———》数据库表里的一行数据</li>
    </ul>
  </li>
  <li>ORM 操作流程：
    <ul>
      <li>创建数据库，设计表结构和字段</li>
      <li>使用 MySQLdb 来连接数据库，并编写数据访问层代码</li>
      <li>业务逻辑层去调用数据访问层执行数据库操作</li>
    </ul>
  </li>
  <li>
    <p>Django 的优势：
Django 的优势还有 Web 界面调试， 丰富的第三方库和文档，强大的ORM模块支持。Django的ORM操作本质上会根据对接的数据库引擎，翻译成对应的sql语句；所有使用Django开发的项目无需关心程序底层使用的是 MySQL、Oracle、sqlite….，如果数据库迁移，只需要更换Django的数据库引擎即可。</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">Q()</code> 可以构造比 Django 自身函数更复杂的SQL查询条件和逻辑关系，然后Q对象可以直接传给filter。例如: <code class="language-plaintext highlighter-rouge">Q(status='COMPLETED', result='agree') | Q(status='RUNNING') </code></p>
  </li>
  <li>
    <p>filter 和 get 的区别以及如何判断为空：
<code class="language-plaintext highlighter-rouge">TABLE.objects.filter(id=2)</code>  ，得到一个集合对象，集合里只有一个，跟上 <code class="language-plaintext highlighter-rouge">first()</code> 或者<code class="language-plaintext highlighter-rouge">[0]</code>取到一个具体对象。判断是否为空使用 <code class="language-plaintext highlighter-rouge">if not XXX</code>。<br />
 <code class="language-plaintext highlighter-rouge">TABLE.objects.get(id=2)[0]</code>，得到一个单独的对象，确定能找到，可以用，如果找到多个或者没有的，都报异常错误。等同于 <code class="language-plaintext highlighter-rouge">TABLE.objects.filter(id=2)[0]</code> 的用法。判断是否为空使用 <code class="language-plaintext highlighter-rouge">is None</code>。</p>
  </li>
  <li>update 和 save 区别:update 可以结合 filter 一次更新多条数据，save一次只能更新一条数据。</li>
  <li>排序 order_by(<code class="language-plaintext highlighter-rouge">field_name</code>) : 默认是是从小到大顺序，逆序则需要在 <code class="language-plaintext highlighter-rouge">field_name</code> 前加上减号<code class="language-plaintext highlighter-rouge">-</code>。</li>
  <li>django获取某一个字段的列表:
    <ul>
      <li>values方法可以获取number字段的字典列表。</li>
      <li>values_list可以获取number的元组列表。</li>
      <li>values_list方法加个参数flat=True可以获取number的值列表。</li>
    </ul>
  </li>
  <li>get_or_create(),之前文章中也提到过,有就获取过来，没有就创建，用它可以避免重复，但是速度可以会慢些，因为要先尝试获取。 返回数据是一个tuple两个值：(size, created)</li>
  <li>排序: <code class="language-plaintext highlighter-rouge">filter(XXX).order_by('-pub_date','headline')</code></li>
  <li>总共5位，其中有两位小数，DecimalField: <code class="language-plaintext highlighter-rouge">DecimalField(max_digits = 5,decimal_places = 2)</code></li>
</ol>

<h2 id="二django-orm-聚合和分页">二、Django ORM 聚合和分页</h2>

<p>聚合: SQL基本函数，聚合函数对一组值执行计算，并返回单个值。除了 COUNT 以外，聚合函数都会忽略空值。 常见的聚合函数有AVG / COUNT / MAX / MIN /SUM 等</p>

<h4 id="aggregate">Aggregate</h4>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>from django.db.models import Avg, Sum, Max, Min, Count # 求Book价格平均值
models.Book.objects.all().aggregate(Sum("price"))
</code></pre></div></div>

<p>通过 <code class="language-plaintext highlighter-rouge">aggregate</code> 可以实现 <code class="language-plaintext highlighter-rouge">filter</code> 过滤的条件后对某个字段加总、求平均等操作。</p>

<h4 id="annotate">annotate</h4>
<p><code class="language-plaintext highlighter-rouge">annotate</code> 可以实现更强大的功能： 分组并统计。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> msgS = MessageTab.objects.values_list('msg_status').annotate(Count('id'))
</code></pre></div></div>
<h4 id="分页">分页</h4>
<p>数据库分页只需要简单用[start:end]截取 QuerySet 的结果集就可以。
但是这样分页拿不到所有符合条件的数据条数。</p>

<p><a href="https://www.cnblogs.com/inns/p/5516539.html">详情链接</a></p>

<h2 id="三django-关于优化执行时间">三、Django 关于优化执行时间</h2>

<p>Django QuerySet是懒执行的，只有访问到对应数据的时候，才会去访问数据库。另外如果你再次读取查询到的数据，将不会触发数据库的访问。</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>blogs = Blog.objects.filter(category='django') # 这里不会访问数据     
if blogs: # 这里需要访问数据，因此会执行数据库查询
randomBlog = blogs[0]# 再次读取，并不会访问数据库
blog = Blog.objects.get(id=124)# 访问一次数据库
author = blog.author # 再次访问数据库
</code></pre></div></div>
<h4 id="django-的加快办法">Django 的加快办法</h4>
<p>总的原则是 <strong>尽可能减少对database的访问次数</strong>，例如把需要for循环多次请求的query一次全部提取出来再做进一步python的筛选和计算，即便会因此产生join问题、大量for循环和重复计算的问题。</p>

<blockquote>
  <p>实例操作证明：通过把query从520个减少到10个，访问时间从2700ms降低到430ms，整体接口访问时间从6s降低到1s左右。(真实要看server当前访问的对database访问的压力，既有压力越大那么可能请求多的情况下速度更慢)</p>
</blockquote>

<p>从 Django 官网和其他地方得到的已知的办法有：</p>
<ol>
  <li>拿到<code class="language-plaintext highlighter-rouge">queryset</code>后先用<code class="language-plaintext highlighter-rouge">if</code>判断一下是否为<code class="language-plaintext highlighter-rouge">None</code>，这样 django 会把 queryset 真正去<code class="language-plaintext highlighter-rouge">access Database</code>然后把结果放入<code class="language-plaintext highlighter-rouge">cache</code>。这样之后再去<code class="language-plaintext highlighter-rouge">for</code>循环读取这个<code class="language-plaintext highlighter-rouge">queryset</code>变量就不会重复<code class="language-plaintext highlighter-rouge">access Database</code>。</li>
  <li>判断数据是否存在用<code class="language-plaintext highlighter-rouge">exists</code>而不是<code class="language-plaintext highlighter-rouge">len</code> 或 <code class="language-plaintext highlighter-rouge">count</code>
exists = Blog.objects.filter(category=’django’).exists()</li>
  <li>获取数据的数量使用<code class="language-plaintext highlighter-rouge">queryset.count()</code> 而不是用<code class="language-plaintext highlighter-rouge">len(queryset)</code>获取长度。前者是 select count()语法，后者会返回整个查询结果集 :
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>count = Blog.objects.filter(category='django').count()
</code></pre></div>    </div>
  </li>
  <li>如果你只想获取外键的 id, 通过 <code class="language-plaintext highlighter-rouge">fk_id</code> 的方法获取要优于 <code class="language-plaintext highlighter-rouge">fk.id</code> 的方式。<code class="language-plaintext highlighter-rouge">fk.id</code> 的方式会为子表内容保存额外的数据库查询。</li>
  <li><strong>筛选数据：</strong> 如果你明确知道需要使用的数据，那就没没必要查询数据库中所有列的数据。比如使用<code class="language-plaintext highlighter-rouge">values()</code> 返回的是以字典的形式返回每一条数据，而 <code class="language-plaintext highlighter-rouge">values_list()</code> 返回的是每条数据元组的列表。</li>
  <li><strong>筛选数据：</strong> 使用 queryset.only 与 difer:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>blogs = Blog.objects.filter(category='django').only('author','title').select_related('author')
blogs = Blog.objects.filter(category='django').defer('description').select_related('author')
</code></pre></div>    </div>
  </li>
  <li>builk_create() 可以执行批量的插入：
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>querysetlist=[]
for i in resultlist:
 querysetlist.append(Account(name=i))        
Account.objects.bulk_create(querysetlist)
</code></pre></div>    </div>
    <blockquote>
      <p>create()每保存一条就执行一次SQL，而bulk_create()是执行一条SQL存入多条数据，做会快很多！当然用列表解析代替 for 循环会更快。</p>
    </blockquote>
  </li>
</ol>

<h4 id="python的加快办法">Python的加快办法</h4>

<ol>
  <li>少用split，多使用他人开发好的Library。</li>
  <li>多构造和使用复杂的数据结构(比如dict)，这样更容易理清代码的逻辑关系、也有助于解决牵扯多个model时的bussiness复杂逻辑处理的问题。</li>
  <li>正向查询：以使用外键的表为主，以外键为id的表数据为条件。B中某个具体实例所关联的A。
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>models.ForeignKey(A)
A.B_set.all()    //比下面的方法多消耗0.2-0.3秒
B.objects.filter(A)  //更快
</code></pre></div>    </div>
  </li>
  <li>反向查询: 想查询A 中某个具体实例所关联的 B</li>
  <li>join 会比 + 更快</li>
</ol>

<h2 id="四django-的时区问题">四、Django 的时区问题</h2>
<p>很多时候，即使设置了setting里的timezone，可是使用datetime类型的field访问数据库还是会有warning。所以转换时区常常出现。</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>from pytz import timezone
cst_tz = timezone('Asia/Shanghai')  
utc_tz = timezone('UTC')  
now = datetime.now().replace(tzinfo=cst_tz)  
</code></pre></div></div>

<h2 id="五django-signal">五、Django Signal</h2>
<p>信号也可以称为钩子。它可以在 model 某些操作之前或之后立刻执行某些命令。</p>

<p>特别的是update方法没有信号量，需要自己写。</p>

<p>Model_signals</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pre_init                        # Django中的model对象执行其构造方法前,自动触发
post_init                       # Django中的model对象执行其构造方法后,自动触发
pre_save                        # Django中的model对象保存前,自动触发
post_save                       # Django中的model对象保存后,自动触发
pre_delete                      # Django中的model对象删除前,自动触发
post_delete                     # Django中的model对象删除后,自动触发
m2m_changed                     # Django中的model对象使用m2m字段操作数据库的第三张表(add,remove,clear,update),自动触发
class_prepared                  # 程序启动时,检测到已注册的model类,对于每一个类,自动触发
</code></pre></div></div>
<p>特别的，post_save 接收到的参数里created可以判断是否是第一次添加记录。</p>

<p>Managemeng_signals</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pre_migrate                     # 执行migrate命令前,自动触发
post_migrate                    # 执行migrate命令后,自动触发
</code></pre></div></div>

<p>Request/response_signals</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>request_started                 # 请求到来前,自动触发
request_finished                # 请求结束后,自动触发
got_request_exception           # 请求异常时,自动触发
</code></pre></div></div>

<p>Test_signals</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>setting_changed                 # 配置文件改变时,自动触发
template_rendered               # 模板执行渲染操作时,自动触发
Datebase_Wrapperd
connection_created              # 创建数据库连接时,自动触发
</code></pre></div></div>

<p>还可以自行定义其他signal。</p>

<h2 id="六django-class-view-method">六、Django Class-View method</h2>
<p>基于函数的视图的问题在于，虽然它们很好地覆盖了简单的情形，但是不能扩展或自定义它们，即使是一些简单的配置选项，这让它们在现实应用中受到很多限制。</p>

<p>基于类的通用视图然后应运而生，目的与基于函数的通用视图一样，就是为了使得视图的开发更加容易。</p>

<h2 id="七调试">七、调试</h2>
<p>加入<code class="language-plaintext highlighter-rouge">import pdb;pdb.set_trace()</code>这一行代码，之后访问该方法，命令行端会停在这里，等待手动输入python命令。</p>

<p>用 PyCharm 调试效果会更好。</p>

<h2 id="八pip-安装-requirementstxt">八、pip 安装 requirements.txt</h2>
<p>生成requirements.txt文件</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip freeze &gt; requirements.txt
</code></pre></div></div>

<p>安装requirements.txt依赖</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip install -r requirements.txt
</code></pre></div></div>

<h2 id="九migrate-和makemigrations的差别">九、migrate 和makemigrations的差别</h2>

<p><code class="language-plaintext highlighter-rouge">python3 manger.py makemigrations</code> 相当于在该app下建立 migrations目录，并记录下你所有的关于modes.py的改动，比如0001_initial.py， 但是这个改动还没有作用到数据库。</p>

<p>在此之后执行命令<code class="language-plaintext highlighter-rouge">python3 manager.py migrate</code>
将该改动作用到数据库文件，比如产生table之类。</p>

<p>后来有种解释补充说，migrate是把别人的修改部署到自己这里。</p>

<h2 id="参考">参考</h2>
<p><a href="https://blog.csdn.net/aaazz47/article/details/78914956/">Django ForeignKey 反向查询中 filter 和 _set的效率对比</a>
<a href="https://www.cnblogs.com/renpingsheng/p/7566647.html">Django中的信号及其用法</a>
<a href="https://blog.csdn.net/AyoCross/article/details/68951413">django中聚合aggregate和annotate GROUP BY的使用方法</a>
<a href="https://blog.csdn.net/Ahri_J/article/details/73610365">Django 数据查询性能优化最佳实践</a></p>

<p><a href="https://www.cnblogs.com/inns/p/5516539.html">QuerySet的分页和排序</a></p>]]></content><author><name>荒岛书生</name><email>lidaxiang0@outlook.com</email></author><category term="Python" /><category term="work" /><category term="Python3" /><category term="Django" /><summary type="html"><![CDATA[总结 Django Framework 使用过程中的不常遇到的技巧经验，以备后用。内容包括但不限于 ORM 模型、Static、Templates、Admin 模块等原生 Django 的功能。]]></summary></entry><entry><title type="html">Django Crontab</title><link href="https://www.lidaxiang.cn/python/django-crontab" rel="alternate" type="text/html" title="Django Crontab" /><published>2018-12-11T00:00:00+08:00</published><updated>2018-12-11T00:00:00+08:00</updated><id>https://www.lidaxiang.cn/python/django-crontab</id><content type="html" xml:base="https://www.lidaxiang.cn/python/django-crontab"><![CDATA[<p>Django-crontab实现Django定时任务,因为celery 插件学习曲线较大，这个小的需求就使用django-crontab 解决。</p>

<!---more--->

<h2 id="安装">安装</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip install django-crontab
</code></pre></div></div>

<p>添加app名称到 settings.py中</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>INSTALLED_APPS = (
        'django_crontab',
        ...
    )
</code></pre></div></div>

<p>settings 配置定时任务:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CRONJOBS = [
    ('*/5 * * * *', 'myapp.cron.my_scheduled_job')
]
</code></pre></div></div>

<p>cronjob 时间配置说明:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>5 4 * * * At 04:05.
5 1/2 * * * //At minute 5 past every 2nd hour from 1 through 23.
* */2 * * * //At every minute past every 2nd hour.
12 12 2 * * //At 12:12 on day-of-month 2
</code></pre></div></div>

<p>5个参数从左到右分别是： 分钟、小时、天数、月份、年份。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>*	any value
,	value list separator
-	range of values
/	step values
</code></pre></div></div>

<h2 id="启动">启动</h2>

<ol>
  <li>以上都完成后，需要执行
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python3 manage.py crontab add
</code></pre></div>    </div>
    <p>将任务添加并生效。</p>
  </li>
  <li>3显示当前的定时任务
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python3 manage.py crontab show
</code></pre></div>    </div>
  </li>
  <li>删除所有定时任务
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python3 manage.py crontab remove
</code></pre></div>    </div>
  </li>
  <li>重启django服务。 执行 <code class="language-plaintext highlighter-rouge">corntab -e </code>
应该是可以看到系统中创建了该定时任务。</li>
</ol>

<p>说到底，只是django-crontab插件对linux底层的调用，不确定这个方法在windows 上是否生效。
```</p>

<h2 id="参考列表">参考列表</h2>
<p><a href="https://blog.csdn.net/sinat_21302587/article/details/72831002">django-crontab 定时执行任务方法</a></p>

<p><a href="https://github.com/kraiz/django-crontab">利用 Django REST framework 编写 RESTful API（drf的filter）</a></p>

<p><a href="https://crontab.guru/">cron时间配置</a></p>]]></content><author><name>荒岛书生</name><email>lidaxiang0@outlook.com</email></author><category term="Python" /><category term="work" /><category term="Python3" /><category term="Django" /><category term="Crontab" /><summary type="html"><![CDATA[Django-crontab实现Django定时任务,因为celery 插件学习曲线较大，这个小的需求就使用django-crontab 解决。]]></summary></entry></feed>