<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>日暮酒醒</title><link>http://blog.bigfoot.xin/</link><description>满天风雨下西楼</description><item><title>grid 布局</title><link>http://blog.bigfoot.xin/post/26.html</link><description>&lt;h3 id=&quot;h3-1-code-align-content-code-code-justify-content-code-grid-template-columns-grid-template-rows-&quot;&gt;&lt;a name=&quot;1. &lt;code&gt;align-content&lt;/code&gt;、&lt;code&gt;justify-content&lt;/code&gt;是设置格子的（通过grid-template-columns/grid-template-rows定义的）&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. &lt;code&gt;align-content&lt;/code&gt;、&lt;code&gt;justify-content&lt;/code&gt;是设置格子的（通过grid-template-columns/grid-template-rows定义的）&lt;/h3&gt;&lt;h3 id=&quot;h3-2-code-align-items-code-code-justify-items-code-code-align-self-code-code-justify-self-code-display-grid-&quot;&gt;&lt;a name=&quot;2. &lt;code&gt;align-items&lt;/code&gt;、&lt;code&gt;justify-items&lt;/code&gt;、&lt;code&gt;align-self&lt;/code&gt;、&lt;code&gt;justify-self&lt;/code&gt;都是设置格子内的元素（也就是设置了display:grid的元素的子元素）&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. &lt;code&gt;align-items&lt;/code&gt;、&lt;code&gt;justify-items&lt;/code&gt;、&lt;code&gt;align-self&lt;/code&gt;、&lt;code&gt;justify-self&lt;/code&gt;都是设置格子内的元素（也就是设置了display:grid的元素的子元素）&lt;/h3&gt;</description><pubDate>Fri, 05 May 2023 09:08:52 +0800</pubDate></item><item><title>laravel队列的retry_after和timeout</title><link>http://blog.bigfoot.xin/post/25.html</link><description>&lt;blockquote&gt;
&lt;p&gt;最近执行一个job，发现有一个耗时较长的任务，执行到第90秒的时候，就会报&lt;code&gt;Illuminate\Queue\MaxAttemptsExceededExceptio&lt;/code&gt;的错误，而任务最终还是成功执行了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;h3-u539Fu56E0&quot;&gt;&lt;a name=&quot;原因&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;原因&lt;/h3&gt;&lt;p&gt;发现是因为retry_after配置的是90秒，而任务的timeout是300秒，这样任务执行到90秒的时候会重新执行这个任务，但由于任务设置了tries=1，只能执行一次，所以就报错了。那为什么任务最终还是成功执行了呢？因为任务设置的timeout是300秒，第一次执行的时候花了95秒，没有达到timeout自然不会判定为失败了。&lt;/p&gt;
&lt;h3 id=&quot;h3-u89E3u51B3u529Eu6CD5&quot;&gt;&lt;a name=&quot;解决办法&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;解决办法&lt;/h3&gt;&lt;p&gt;修改config/queue.php中，对应队列驱动的retry_after，我用的是redis驱动，所以改redis对应的配置就行了&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2023/03/202303051336594620744.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;注意retry_after需要比任务的timeout多几秒，这将确保处理给定任务的 worker 总是在重试作业之前被杀死。如果你的timeout 选项比你的 retry_after 配置值长，你的任务可能会被处理两次。&lt;/p&gt;
</description><pubDate>Sun, 05 Mar 2023 13:24:45 +0800</pubDate></item><item><title>Laravel中使用Algolia Search</title><link>http://blog.bigfoot.xin/post/24.html</link><description>&lt;h3 id=&quot;h3--algolia-&quot;&gt;&lt;a name=&quot;一、Algolia介绍&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;一、Algolia介绍&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://www.algolia.com/&quot; title=&quot;Algolia&quot;&gt;Algolia&lt;/a&gt; 是一个托管搜索引擎，提供全文、数值和分面搜索，能够从第一次击键开始提供实时结果。 Algolia强大的API可让您在网站和移动应用程序中快速无缝地实施搜索。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;简单来说，我们可以将数据存储到algolia，algolia会将数据进行全文索引，而且提供了丰富的API，我们可以在前端、后端使用这些api对数据进行管理、搜索。&lt;/p&gt;
&lt;h4 id=&quot;h4-1-algolia-github-&quot;&gt;&lt;a name=&quot;1. 登录algolia，建议选择github登录&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 登录algolia，建议选择github登录&lt;/h4&gt;&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151057342230608.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;h4-2-&quot;&gt;&lt;a name=&quot;2. 创建应用&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 创建应用&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;输入应用名称，选择付费方案，我们可以选择免费版，然后下一步。注意免费版只能存10000条数据，支持每月10000次搜索。&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151436363485247.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;选择数据托管区域，建议选择香港，延迟更低，左下角可以预览从不同区域发出请求到你所选择的区域所花的大致时间。然后点击右下角的按钮进入应用预览。&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151443576623497.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用预览页面，接受隐私条款什么的，点击创建应用，你的应用就创建成功了。&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151452094490287.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;h4-3-&quot;&gt;&lt;a name=&quot;3. 查看应用秘钥&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. 查看应用秘钥&lt;/h4&gt;&lt;p&gt;进入后台面板后，点击Api Keys&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151546433566532.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;可以看到应用的ID、API KEY，这些我们后面会用到。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151552078155537.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3--laravel-algolia&quot;&gt;&lt;a name=&quot;二、Laravel中集成Algolia&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;二、Laravel中集成Algolia&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;laravel/scout包其实是自带Algolia驱动的，只要在config/scout.php 中配置Algolia应用的id和secret，然后安装&lt;code&gt;algolia/algoliasearch-client-php&lt;/code&gt;就能使用了。但是根据Algolia文档的说明，他们提供了laravel/scout包的替代品：&lt;a href=&quot;https://github.com/algolia/scout-extended&quot; title=&quot;algolia/scout-extended&quot;&gt;algolia/scout-extended&lt;/a&gt;，algolia/scout-extended是基于最新的laravel/scout构建的，在laravel/scout的基础上增加了“零停机时间导入”、“聚合器”等功能，所以我们选择使用&lt;code&gt;algolia/scout-extended&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;请先阅读laravel/scout的文档，了解scout的基本使用，再查看下面的教程&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;h4-1-algolia-scout-extended&quot;&gt;&lt;a name=&quot;1. 安装algolia/scout-extended&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 安装algolia/scout-extended&lt;/h4&gt;&lt;p&gt;具体安装和配置步骤可以查看官方文档：&lt;a href=&quot;https://www.algolia.com/doc/framework-integration/laravel/getting-started/installation/?client=php&quot;&gt;https://www.algolia.com/doc/framework-integration/laravel/getting-started/installation/?client=php&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;注意装了scout-extended包后，我们就不用再安装&lt;code&gt;algolia/algoliasearch-client-php&lt;/code&gt;了，scout-extended的依赖已经包含了此包。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;配置algolia参数，setting_path是索引配置文件的保存目录&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151623446166131.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;配置config/scout.php中的prefix，设置为当前env，这样能够让不同环境的索引数据保持独立&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151622394412542.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;h4-2-&quot;&gt;&lt;a name=&quot;2. 常用命令&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 常用命令&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;生成模型的索引配置文件，比如索引语言、可搜索字段等，这些也可以在algolia后台面板设置&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;php artisan scout:optimize&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同步algolia服务器和本地的索引配置文件：&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;php artisan scout:sync&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;导入数据&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;php artisan scout:import&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;import命令执行流程：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151637183131867.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;零停机时间导入&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;php artisan scout:reimport&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;reimport命令执行流程：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151632287332236.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;可以看出来，import命令是先清空索引的数据，再导入，对线上影响比较大。而reimport命令是先创建一个临时索引，将数据导入临时索引，再使用临时索引替换正式索引，整个过程对线上基本无影响。所以&lt;strong&gt;建议使用reimport命令&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&quot;h3--&quot;&gt;&lt;a name=&quot;三、查询建议&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;三、查询建议&lt;/h3&gt;&lt;p&gt;algolia提供了查询建议功能，查询建议其实也是一个索引，将它和别的索引关联，就能根据其他索引的搜索频次、命中次数等，将查询词存储到查询建议索引。具体可参考：&lt;a href=&quot;https://www.algolia.com/doc/guides/building-search-ui/ui-and-ux-patterns/query-suggestions/js/&quot;&gt;https://www.algolia.com/doc/guides/building-search-ui/ui-and-ux-patterns/query-suggestions/js/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;效果示意图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151703131900440.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3--&quot;&gt;&lt;a name=&quot;四、前端集成&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;四、前端集成&lt;/h3&gt;&lt;p&gt;前端可以使用官方的autocomplete.js或者InstantSearch.js，具体请查看：&lt;/p&gt;
&lt;p&gt;InstantSearch.js： &lt;a href=&quot;https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/js/&quot; title=&quot;https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/js/&quot;&gt;https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/js/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;autocomplete.js：&lt;a href=&quot;https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/&quot; title=&quot;https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/&quot;&gt;https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;下图是我使用autocomplete.js的效果：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212151653598138880.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
</description><pubDate>Thu, 15 Dec 2022 10:43:59 +0800</pubDate></item><item><title>VSCode设置自动换行</title><link>http://blog.bigfoot.xin/post/23.html</link><description>&lt;blockquote&gt;
&lt;p&gt;在使用VSCode编辑器时，一行过长会影响阅读，我们可以开启自动换行，并设置每行长度&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;h3-1-&quot;&gt;&lt;a name=&quot;1. 点击左下角设置图标，点击“设置”&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 点击左下角设置图标，点击“设置”&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212141215039669373.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3-2-wordwrap-code-word-wrap-code-on-&quot;&gt;&lt;a name=&quot;2. 顶部搜索框搜索wordwrap，将&lt;code&gt;Word Wrap&lt;/code&gt;设置为”on”，这样代码就能根据编辑器当前视区宽度自动换行了。&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 顶部搜索框搜索wordwrap，将&lt;code&gt;Word Wrap&lt;/code&gt;设置为”on”，这样代码就能根据编辑器当前视区宽度自动换行了。&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;注意下面还有一个配置&lt;code&gt;Word Wrap Column&lt;/code&gt;，这是手动设置换行字符数，而且只有&lt;code&gt;Word Wrap&lt;/code&gt;设置为以下两种值的时候才会生效&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;wordWrapColumn：根据设置的换行字符数&lt;code&gt;Word Wrap Column&lt;/code&gt;进行换行&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;bounded：根据设置的换行字符数&lt;code&gt;Word Wrap Column&lt;/code&gt;和编辑器视区宽度中的较小值去换行&lt;/p&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://static.bigfoot.xin/zb_users/upload/2022/12/202212141219289304601.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
</description><pubDate>Wed, 14 Dec 2022 12:11:10 +0800</pubDate></item><item><title>Conda介绍</title><link>http://blog.bigfoot.xin/post/22.html</link><description>&lt;blockquote&gt;
&lt;p&gt;conda可以理解为一个工具，也是一个可执行命令，其核心功能是包管理和环境管理。包管理与pip的使用方法类似似，环境管理则是允许用户方便滴安装不同版本的python环境并在不同环境之间快速地切换。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;h3--conda-&quot;&gt;&lt;a name=&quot;一、conda的设计理念&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;一、conda的设计理念&lt;/h3&gt;&lt;p&gt;conda将几乎所有的工具、第三方包都当作package进行管理，甚至包括python 和conda自身。Anaconda是一个打包的集合，里面预装好了conda、某个版本的python、各种packages等。&lt;/p&gt;
&lt;h3 id=&quot;h3--conda-&quot;&gt;&lt;a name=&quot;二、conda常用的命令&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;二、conda常用的命令&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;检验是否安装及当前conda的版本&lt;/li&gt;&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;conda -v&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;查看环境中安装了哪些包，默认是base环境&lt;/li&gt;&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;conda list&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;查看当前存在哪些虚拟环境&lt;/li&gt;&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;conda env list 
conda info -e&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;检查更新当前conda&lt;/li&gt;&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;conda update conda&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;创建Python虚拟环境&lt;/li&gt;&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;创建python版本为x.x，名字为env_name的虚拟环境。env_name文件可以在Anaconda安装目录envs文件下找到&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;conda create -n [env_name] python=x.x
或者克隆
conda create -n your_name --clone env_name&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;激活或者切换虚拟环境&lt;/li&gt;&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Linux&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;source activate [env_name]
conda activate [env_name]&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Windows&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;Windows: activate [env_name]&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;7&quot;&gt;
&lt;li&gt;对虚拟环境中安装额外的包&lt;/li&gt;&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;conda install -n env_name [package]  # 未激活环境
conda install [package]  # 如果已经激活环境&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;8&quot;&gt;
&lt;li&gt;关闭虚拟环境(即从当前环境退出返回使用PATH环境中的默认python版本)&lt;/li&gt;&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;source deactivate
conda deactivate&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;9&quot;&gt;
&lt;li&gt;删除虚拟环境&lt;/li&gt;&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;conda remove -n env_name --all&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;10&quot;&gt;
&lt;li&gt;删除环境中的某个包&lt;/li&gt;&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;conda remove --name $env_name  $package_name &lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;11&quot;&gt;
&lt;li&gt;设置国内镜像&lt;/li&gt;&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;anaconda.org的服务器在国外，安装多个packages时，conda下载的速度经常很慢。清华TUNA镜像源有anaconda仓库的镜像，将其加入conda的配置即可：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;12&quot;&gt;
&lt;li&gt;恢复默认镜像&lt;/li&gt;&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;conda config --remove-key channels&lt;/code&gt;&lt;/pre&gt;
</description><pubDate>Sun, 06 Nov 2022 11:35:09 +0800</pubDate></item><item><title>nohup命令的使用</title><link>http://blog.bigfoot.xin/post/21.html</link><description>&lt;blockquote&gt;
&lt;p&gt;例如，使用nohup命令启动PaddleHub Serving，使用的模型是&lt;code&gt;ch_pp-ocrv3&lt;/code&gt;，这样即使关闭命令行，http服务不会中断&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;nohup hub serving start -m ch_pp-ocrv3 &amp;amp;&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;nohup命令，英文全称 no hang up（不挂起），用于在系统后台不挂断地运行命令，退出终端不会影响程序的运行。nohup 命令，在默认情况下（非重定向时），会输出一个名叫 nohup.out 的文件到当前目录下，如果当前目录的 nohup.out 文件不可写，输出重定向到 $HOME/nohup.out 文件中。&lt;/p&gt;
&lt;/blockquote&gt;
</description><pubDate>Fri, 04 Nov 2022 15:41:37 +0800</pubDate></item><item><title>Python常用库</title><link>http://blog.bigfoot.xin/post/20.html</link><description>&lt;h3 id=&quot;h3--&quot;&gt;&lt;a name=&quot;一、文档处理&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;一、文档处理&lt;/h3&gt;&lt;h4 id=&quot;h4-1-word-&quot;&gt;&lt;a name=&quot;1. 处理word文档：&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 处理word文档：&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;python-docx&lt;/code&gt;，文档地址：&lt;a href=&quot;https://python-docx.readthedocs.io/en/latest/#&quot; title=&quot;https://python-docx.readthedocs.io/en/latest/#&quot;&gt;https://python-docx.readthedocs.io/en/latest/#&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h4 id=&quot;h4-2-excel-&quot;&gt;&lt;a name=&quot;2. 处理excel：&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 处理excel：&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;pandas&lt;/code&gt;，使用pandas的dataFrame可以很方便地处理表格数据，如需读写excel文件，还需安装下面的&lt;code&gt;openpyxl&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;openpyxl&lt;/code&gt;，读写 Excel 2010 xlsx/xlsm文件，文档地址：&lt;a href=&quot;https://openpyxl.readthedocs.io/en/stable/&quot;&gt;https://openpyxl.readthedocs.io/en/stable/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
</description><pubDate>Sat, 29 Oct 2022 11:07:49 +0800</pubDate></item><item><title>DOM常用原生api</title><link>http://blog.bigfoot.xin/post/19.html</link><description>&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Element.getBoundingClientRect()，其提供了元素的大小及其相对于视口的位置。详情：&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;Window.scrollY，返回文档在垂直方向已滚动的像素值。详情：&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;/ol&gt;
</description><pubDate>Fri, 07 Oct 2022 08:03:41 +0800</pubDate></item><item><title>浅谈响应式网站</title><link>http://blog.bigfoot.xin/post/18.html</link><description>&lt;blockquote&gt;
&lt;p&gt;最近在做官网，使用了响应式技术，这样可以让官网兼容不同分辨率的设备。这里总结一下媒体查询断点使用的经验。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;h3--tailwindcss-&quot;&gt;&lt;a name=&quot;一、tailwindcss的媒体查询介绍&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;一、tailwindcss的媒体查询介绍&lt;/h3&gt;&lt;p&gt;我现在用的css框架是tailwindcss，这是一个非常灵活的css框架，包含预定义的细粒度工具类，同时也可以很方便地对其自定义。框架默认内置了以下媒体查询断点：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;断点前缀 (breakpoint prefix)&lt;/th&gt;
&lt;th&gt;最小宽度 (min-width)&lt;/th&gt;
&lt;th&gt;对应的css代码&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;sm&lt;/td&gt;
&lt;td&gt;640px&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/media&quot; title=&quot;&amp;#64;media&quot; class=&quot;at-link&quot;&gt;@media&lt;/a&gt; (min-width: 640px) { … }&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;md&lt;/td&gt;
&lt;td&gt;768px&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/media&quot; title=&quot;&amp;#64;media&quot; class=&quot;at-link&quot;&gt;@media&lt;/a&gt; (min-width: 768px) { … }&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lg&lt;/td&gt;
&lt;td&gt;1024px&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/media&quot; title=&quot;&amp;#64;media&quot; class=&quot;at-link&quot;&gt;@media&lt;/a&gt; (min-width: 1024px) { … }&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xl&lt;/td&gt;
&lt;td&gt;1280px&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/media&quot; title=&quot;&amp;#64;media&quot; class=&quot;at-link&quot;&gt;@media&lt;/a&gt; (min-width: 1280px) { … }&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2xl&lt;/td&gt;
&lt;td&gt;1536px&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://github.com/media&quot; title=&quot;&amp;#64;media&quot; class=&quot;at-link&quot;&gt;@media&lt;/a&gt; (min-width: 1536px) { … }&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;如果不写前缀，默认是对所有设备生效，为了方便叙述，我们把视口宽度定义为viewport，例如：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;!-- p在所有设备上的字体大小都是text-lg --&amp;gt;
&amp;lt;p class=&amp;quot;text-lg&amp;quot;&amp;gt;
&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果加上前缀，就会在viewport&amp;gt;=min-width时，应用后面的class&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;!-- viewport&amp;lt;768px时，字体大小为text-sm；viewport&amp;gt;=768px时，字体大小为text-lg --&amp;gt;
&amp;lt;p class=&amp;quot;text-sm md:text-lg&amp;quot;&amp;gt;
&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;多个断点的情况：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;!-- viewport&amp;lt;768px时，字体大小为text-sm；768px&amp;lt;=viewport&amp;lt;1280px时，字体大小为text-lg；viewport&amp;gt;=1280px时，字体大小为text-xl --&amp;gt;
&amp;lt;p class=&amp;quot;text-sm md:text-lg xl:text-xl&amp;quot;&amp;gt;
&amp;lt;/p&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;未完待续…&lt;/p&gt;
</description><pubDate>Fri, 30 Sep 2022 20:06:42 +0800</pubDate></item><item><title>关于Mysql乐观锁</title><link>http://blog.bigfoot.xin/post/14.html</link><description>&lt;blockquote&gt;
&lt;p&gt;程序开发中，经常碰到的一个问题就是如何避免超卖，例如优惠券的库存是10张，那肯定要避免最后送出的数量超过10。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;例如有个发放优惠券的活动，两个用户同时向服务器发送了领取优惠券的请求，这两个请求我们就命名为请求1和请求2。服务器处理这两个请求之前，数据表如下所示，还剩一张优惠券。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;total（总数量）&lt;/th&gt;
&lt;th&gt;issued (已发放数量)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;洗剪吹优惠券&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;h3-1-&quot;&gt;&lt;a name=&quot;1. 错误的示范&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;1. 错误的示范&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;language-mysql&quot;&gt;//从数据库里取出优惠券，where条件是已发放数量小于总数量
select * from coupons where issued&amp;lt;total where id=1;
//如果结果为空，说明没有库存了
//如果有结果，则执行完发放操作后，已发数量+1
update coupons set issued=issued+1 where id=1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;请求1和请求2同时读取数据库，都取到了记录，再更新，issued变成了11，导致超卖。超卖的原因就是因为，并发请求读到了相同的数据。&lt;/p&gt;
&lt;h3 id=&quot;h3-2-&quot;&gt;&lt;a name=&quot;2. 使用乐观锁解决问题&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;2. 使用乐观锁解决问题&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;说乐观锁之前，先说下悲观锁，悲观锁之所以悲观，是因为“悲观”地先锁住数据，等数据处理完成了，再释放锁。这样可以解决问题，但是效率不高。乐观锁不是先锁数据，而是更新的时候判断条件是否满足。示例如下：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;首先，我们给coupons表增加个version字段，默认值0&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;total（总数量）&lt;/th&gt;
&lt;th&gt;issued (已发放数量)&lt;/th&gt;
&lt;th&gt;version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;洗剪吹优惠券&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;sql语句&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-mysql&quot;&gt;//从数据库里取出优惠券，where条件是已发放数量小于总数量
select * from coupons where issued&amp;lt;total where id=1;
//如果结果为空，说明没有库存了
//如果有结果，因为请求1和请求2同时读取的数据库，读到的version值都是0，更新语句如下
update coupons set issued=issued+1,version=version+1 where id=1 and version=0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;和错误示范的区别在于，更新的时候version递增1，而且限制了verion=当前读出的记录的version值，因为update的where条件字段有索引，会触发行锁，请求1和请求2只能依次更新，比如请求1已经更新完成，这时候version=1，请求2再去更新的时候，version=0不满足条件，也就更新失败了，所以同时有多个请求时，永远只有一条记录更新成功。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt; 总结：给数据表增加version(版本号)字段，初始为0，更新的时候version递增1，并且where条件限制version=当前version，这样就能购保证同一个版本的行记录，不可能同时被两个请求修改。每个请求在更新的时候，如果更新成功，说明issued的值从读出到更新成功这一刻一直没变（如果issued变了，version肯定也变了，version变了就不会更新成功）。错误示范的sql之所以不能保证并发，就是因为更新的时候可能issued已经被别的并发请求先+1了，已经和总数量相等了，但是更新语句还是执行了，最终造成了超卖。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;h3-3-&quot;&gt;&lt;a name=&quot;3. 更宽松的乐观锁&quot; class=&quot;reference-link&quot; href=&quot;#&quot;&gt;&lt;/a&gt;&lt;span class=&quot;header-link octicon octicon-link&quot;&gt;&lt;/span&gt;3. 更宽松的乐观锁&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;还是上面的例子，假如还剩两个未发放，采用version的方法，会发生什么呢？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;name&lt;/th&gt;
&lt;th&gt;total（总数量）&lt;/th&gt;
&lt;th&gt;issued (已发放数量)&lt;/th&gt;
&lt;th&gt;version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;洗剪吹优惠券&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;可想而知，请求1和请求2，还是只有1个请求可以更新成功，即使还剩2个。所以版本号的方案虽然能避免超卖，但是会减少系统吞吐量，明明还有库存，但是确可能会失败。所以可以用更宽松的方式处理：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;update coupons set issued=issued+1 where id=1 and issued&amp;lt;total&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;还是利用了update行锁的特性，update只能排队一个个来，而且限制条件比较宽松，只要issued&amp;lt;total就能更新成功，就算请求1和请求2读到的行记录是一样的，只要update的时候满足条件就能成功update。相比version的方案，这种方法更简单，吞吐量更高。&lt;/p&gt;
</description><pubDate>Sun, 08 May 2022 17:46:19 +0800</pubDate></item></channel></rss>