<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>星光下的赶路人</title><link>https://forstyle.cc/zblog/</link><description></description><item><title>windows端口转发，可转发WSL端口</title><link>https://forstyle.cc/zblog/post/127.html</link><description>&lt;p&gt;windows自带有端口转发命令，没必要安装其他管理软件&lt;br/&gt;&lt;/p&gt;&lt;p&gt;命令如下，将8003端口转发到WSL中的 8003 端口&lt;/p&gt;&lt;pre class=&quot;brush:ps;toolbar:false;&quot;&gt;netsh&amp;nbsp;interface&amp;nbsp;portproxy&amp;nbsp;add&amp;nbsp;v4tov4&amp;nbsp;listenport=8003&amp;nbsp;listenaddress=0.0.0.0&amp;nbsp;connectport=8003&amp;nbsp;connectaddress=127.0.0.1&lt;/pre&gt;&lt;p&gt;查看全部的已配置的转发端口&lt;/p&gt;&lt;pre class=&quot;brush:ps;toolbar:false;&quot;&gt;netsh&amp;nbsp;interface&amp;nbsp;portproxy&amp;nbsp;show&amp;nbsp;all&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;有个服务必须启动&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/07/202607271551552036848.png&quot; alt=&quot;image.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;服务启动后执行以下命令设置开机启动&lt;/p&gt;&lt;pre class=&quot;brush:ps;toolbar:false&quot;&gt;::&amp;nbsp;立即启动&amp;nbsp;IP&amp;nbsp;Helper&amp;nbsp;服务
sc&amp;nbsp;start&amp;nbsp;iphlpsvc

::&amp;nbsp;设置服务开机自动启动（注意&amp;nbsp;start=&amp;nbsp;后面有空格，语法硬性要求）
sc&amp;nbsp;config&amp;nbsp;iphlpsvc&amp;nbsp;start=&amp;nbsp;auto&lt;/pre&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Mon, 27 Jul 2026 15:48:06 +0800</pubDate></item><item><title>windwos和linux下获取当前使用的麦克风型号</title><link>https://forstyle.cc/zblog/post/126.html</link><description>&lt;p&gt;&lt;span style=&quot;white-space-collapse: preserve;&quot;&gt;需求是浏览器获取当前麦克风型号，对不支持的型号做限制，&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space-collapse: preserve;&quot;&gt;最开始想的通过js后去麦克风型号，但是在windows下测试的没问题，到linux系统下就不行了&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space-collapse: preserve;&quot;&gt;历览器输入以下地址可以看到支持的硬件信息&lt;/span&gt;&lt;/p&gt;&lt;pre class=&quot;brush:as3;toolbar:false&quot;&gt;chrome://media-internals/&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/07/202607241784874164512468.png&quot; alt=&quot;image.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;在windows下可以看到支持的型号，&lt;/p&gt;&lt;p&gt;但是在linux下看不到&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/07/202607241784874332449398.png&quot; alt=&quot;image.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space-collapse: preserve;&quot; data-slate-fragment=&quot;JTVCJTdCJTIydHlwZSUyMiUzQSUyMnBhcmFncmFwaCUyMiUyQyUyMmNoaWxkcmVuJTIyJTNBJTVCJTdCJTIydGV4dCUyMiUzQSUyMndpbmR3byVFNCVCOCU4QiVFOSU5QyU4MCVFOCVBNiU4MSVFNCVCRCVCRiVFNyU5NCVBOCUyMHNvdW5kZGV2aWNlJTIwJUU1JUJBJTkzJUVGJUJDJThDbGludXglRTQlQjglOEIlRTQlQkQlQkYlRTclOTQlQTglMjBwdWxzZWN0bCUyMiU3RCU1RCU3RCU1RA==&quot;&gt;windwo下需要使用 sounddevice 库，linux下使用 pulsectl&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space-collapse: preserve;&quot; data-slate-fragment=&quot;JTVCJTdCJTIydHlwZSUyMiUzQSUyMnBhcmFncmFwaCUyMiUyQyUyMmNoaWxkcmVuJTIyJTNBJTVCJTdCJTIydGV4dCUyMiUzQSUyMndpbmR3byVFNCVCOCU4QiVFOSU5QyU4MCVFOCVBNiU4MSVFNCVCRCVCRiVFNyU5NCVBOCUyMHNvdW5kZGV2aWNlJTIwJUU1JUJBJTkzJUVGJUJDJThDbGludXglRTQlQjglOEIlRTQlQkQlQkYlRTclOTQlQTglMjBwdWxzZWN0bCUyMiU3RCU1RCU3RCU1RA==&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;pre class=&quot;brush:python;toolbar:false&quot;&gt;import&amp;nbsp;sys

def&amp;nbsp;get_windows_active_mic():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;Windows&amp;nbsp;系统：通过&amp;nbsp;COM/pycaw&amp;nbsp;接口精确获取当前默认输入的麦克风型号&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;import&amp;nbsp;sounddevice&amp;nbsp;as&amp;nbsp;sd

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;devices&amp;nbsp;=&amp;nbsp;sd.query_devices()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;default_in_id&amp;nbsp;=&amp;nbsp;sd.default.device[0]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;print(&amp;quot;默认录音设备ID：&amp;quot;,&amp;nbsp;default_in_id)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;print(&amp;quot;默认录音设备ID：&amp;quot;,&amp;nbsp;devices[default_in_id])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;devices[default_in_id][&amp;#39;name&amp;#39;]

def&amp;nbsp;get_active_mic_pulsectl():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;import&amp;nbsp;pulsectl
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;pulsectl.Pulse(&amp;#39;get-mic-script&amp;#39;)&amp;nbsp;as&amp;nbsp;pulse:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;获取默认&amp;nbsp;Source&amp;nbsp;的名称
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;server_info&amp;nbsp;=&amp;nbsp;pulse.server_info()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;default_source_name&amp;nbsp;=&amp;nbsp;server_info.default_source_name

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;遍历&amp;nbsp;Source&amp;nbsp;寻找描述信息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;source&amp;nbsp;in&amp;nbsp;pulse.source_list():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;source.name&amp;nbsp;==&amp;nbsp;default_source_name:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;获取&amp;nbsp;friendly&amp;nbsp;名称
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;desc&amp;nbsp;=&amp;nbsp;source.proplist.get(&amp;#39;device.description&amp;#39;)&amp;nbsp;or&amp;nbsp;source.description
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;desc
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;未找到设备&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;f&amp;quot;获取失败:&amp;nbsp;{e}&amp;quot;

def&amp;nbsp;get_active_mic():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(sys.platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;根据操作系统自动路由&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;sys.platform.startswith(&amp;quot;win&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;get_windows_active_mic()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elif&amp;nbsp;sys.platform.startswith(&amp;quot;linux&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;get_active_mic_pulsectl()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;f&amp;quot;暂不支持的操作系统:&amp;nbsp;{sys.platform}&amp;quot;

if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;当前正在使用的麦克风型号:&amp;quot;,&amp;nbsp;get_active_mic())&lt;/pre&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/07/202607241784873900250372.png&quot; alt=&quot;image.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/07/202607241784873938115984.png&quot; alt=&quot;image.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description><pubDate>Fri, 24 Jul 2026 14:17:39 +0800</pubDate></item><item><title>VLLM服务端启动ChineseErrorCorrector3-4B模型</title><link>https://forstyle.cc/zblog/post/125.html</link><description>&lt;p&gt;先贴命令&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;vllm&amp;nbsp;serve&amp;nbsp;/www/models/Qwen/ChineseErrorCorrector3-4B&amp;nbsp;\
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--max-model-len&amp;nbsp;10240&amp;nbsp;\
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--dtype&amp;nbsp;float16&amp;nbsp;\
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--max-num-batched-tokens&amp;nbsp;10240&amp;nbsp;\
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--gpu-memory-utilization&amp;nbsp;0.4&amp;nbsp;\
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--max-num-seqs&amp;nbsp;512&amp;nbsp;\
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--host&amp;nbsp;0.0.0.0&amp;nbsp;\
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--port&amp;nbsp;8004&amp;nbsp;\
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--served-model-name&amp;nbsp;csc-3B&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这条命令的作用：&lt;span style=&quot;font-size: 16px;&quot;&gt;用 vLLM 高性能推理框架，把中文纠错模型 ChineseErrorCorrector3-4B 启动成兼容 OpenAI 接口格式的 HTTP 推理服务&lt;/span&gt;，外部程序可通过 8004 端口调用文本纠错能力。&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/07/202607121783864288474784.png&quot; alt=&quot;image-20260611145021-dksod7v.png&quot; data-href=&quot;&quot; /&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/07/202607121783864369730328.png&quot; alt=&quot;image-20260611145026-v1xrszm.png&quot; data-href=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;vllm servevLLM 提供的服务启动子命令，自动内置 OpenAI 兼容 REST API（/v1/completions、/v1/chat/completions），无需自己封装接口。&lt;/p&gt;
&lt;p&gt;/www/models/Qwen/ChineseErrorCorrector3-4B本地模型权重文件路径，指向 4B 参数中文文本纠错模型（CSC 错别字校对模型）。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;code&gt;--max-model-len 10240&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;模型最大支持输入 + 输出总 token 长度 10240。&lt;/p&gt;
&lt;p&gt;适合长文本纠错场景（长篇文档、案卷、文章批量校对），超过长度会截断输入。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;--dtype float16模型权重 / 推理计算使用 FP16 半精度：&lt;/p&gt;
&lt;blockquote&gt;显存占用减半，相比 FP32 节省大量显存；速度更快，绝大多数 Nvidia GPU 原生支持 FP16 加速；纠错类模型对精度不敏感，FP16 不会明显降低校对准确率。&lt;/blockquote&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;code&gt;--max-num-batched-tokens 10240&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;单次推理批处理中，所有并发请求的 token 总和上限 10240。&lt;/p&gt;
&lt;p&gt;用来防止瞬间大量长文本请求撑爆显存，和 &lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;code&gt;max-model-len&lt;/code&gt;&lt;/span&gt; 配套管控显存负载。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;--gpu-memory-utilization 0.4限制模型 + KV 缓存最多占用40% GPU 显存（0.4 = 40%）。&lt;/p&gt;
&lt;p&gt;预留 60% 显存给系统、其他进程、突发 KV 缓存；多模型混跑、显卡同时跑其他任务时常用低利用率；纯单模型独占显卡可调高至 0.8~0.95 提升并发。&lt;/p&gt;
&lt;p&gt;--max-num-seqs 512服务同时允许最多 512 条并行推理序列（并发请求）。&lt;/p&gt;
&lt;p&gt;短文本纠错场景可拉高，支持高 QPS；长文本场景建议降低，避免 KV 缓存暴涨 OOM。&lt;/p&gt;
&lt;p&gt;--host 0.0.0.0监听本机所有网卡地址，允许局域网 / 其他服务器远程访问接口；若写 127.0.0.1 则仅本机可调用，外部无法连接。&lt;/p&gt;
&lt;p&gt;--port 8004HTTP 服务监听端口，调用地址示例：http://服务器IP:8004/v1/chat/completions&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;code&gt;--served-model-name csc-3B&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;API 请求时需要指定的 &lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;code&gt;model&lt;/code&gt;&lt;/span&gt; 参数名称，不用填冗长模型路径。&lt;/p&gt;
&lt;p&gt;调用示例请求体片段：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
&amp;nbsp;&amp;nbsp;&quot;model&quot;:&amp;nbsp;&quot;csc-3B&quot;,
&amp;nbsp;&amp;nbsp;&quot;prompt&quot;:&amp;nbsp;&quot;需要纠错的原文&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description><pubDate>Sun, 12 Jul 2026 21:46:23 +0800</pubDate></item><item><title>windows右键管理</title><link>https://forstyle.cc/zblog/post/124.html</link><description>&lt;p&gt;windows11设计之初是为了简化右键，但是很多功能都隐藏起来了，要不通过shift + 右键出来详细右键，要不就得点详情来看，通过以下方法可以直接换为旧版的右键菜单。&lt;/p&gt;&lt;p&gt;开始菜单搜索cmd，以管理员身份打开&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/05/202605271779845975404304.png&quot; alt=&quot;image.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;运行以下命令&lt;br/&gt;&lt;/p&gt;&lt;pre class=&quot;brush:bash;toolbar:false&quot;&gt;reg.exe&amp;nbsp;add&amp;nbsp;&amp;quot;HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}&amp;quot;&amp;nbsp;/f
reg.exe&amp;nbsp;add&amp;nbsp;&amp;quot;HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32&amp;quot;&amp;nbsp;/f&amp;nbsp;/ve&lt;/pre&gt;&lt;p&gt;再执行&lt;/p&gt;&lt;pre class=&quot;brush:bash;toolbar:false&quot;&gt;taskkill&amp;nbsp;/f&amp;nbsp;/im&amp;nbsp;explorer.exe
start&amp;nbsp;explorer.exe&lt;/pre&gt;&lt;p&gt;然后点右键就是旧版的菜单了。&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/05/202605271779846029938472.png&quot; alt=&quot;image.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;还有一个好用的右键菜单管理工具推荐。&lt;/p&gt;&lt;p&gt;ContextMenuManager&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/BluePointLilac/ContextMenuManager/releases/tag/3.3.3.1&quot; target=&quot;_blank&quot; textvalue=&quot;下载链接&quot;&gt;下载链接&lt;/a&gt;&lt;/p&gt;&lt;p&gt;下载完后不需要安装直接打开就能用&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/05/202605271779846115155709.png&quot; alt=&quot;image.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;可以管理文件、文件夹、目录等等各种右键菜单。&lt;/p&gt;&lt;p&gt;我现在在目录里面右键就只剩下这些了。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/05/202605271779846186351198.png&quot; alt=&quot;image.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;简化了很多。&lt;br/&gt;&lt;/p&gt;</description><pubDate>Wed, 27 May 2026 09:35:57 +0800</pubDate></item><item><title>从其他linux服务器拉取文件到当前服务器</title><link>https://forstyle.cc/zblog/post/123.html</link><description>&lt;p&gt;项目需要，当前服务器通过堡垒机连接，不知道密码，但是其他服务器密码知道，也不能上传文件，所以，只能通过其他服务器将文件传输到当前服务器，其他服务器也没有安装nginx等网络服务，因此只能从过scp命令传输文件&lt;/p&gt;&lt;p&gt;拉取单个文件&lt;/p&gt;&lt;pre class=&quot;brush:bash;toolbar:false&quot;&gt;scp&amp;nbsp;root@192.168.1.100:/data/test.txt&amp;nbsp;./&lt;/pre&gt;&lt;p&gt;拉取整个文件夹&lt;br/&gt;&lt;/p&gt;&lt;pre class=&quot;brush:bash;toolbar:false&quot;&gt;scp&amp;nbsp;-r&amp;nbsp;root@192.168.1.100:/data/abc&amp;nbsp;/home/&lt;/pre&gt;&lt;p style=&quot;text-indent: 0em; text-align: left;&quot;&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/05/202605181779072732822744.png&quot; alt=&quot;image.png&quot; style=&quot;float: left;&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;把当前文件推送到远程服务器&lt;br/&gt;&lt;/p&gt;&lt;pre class=&quot;brush:bash;toolbar:false&quot;&gt;scp&amp;nbsp;./test.txt&amp;nbsp;root@192.168.1.100:/data/&lt;/pre&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Mon, 18 May 2026 10:48:16 +0800</pubDate></item><item><title>从一台doris导入表结构和数据到另一台doris</title><link>https://forstyle.cc/zblog/post/119.html</link><description>&lt;p id=&quot;w-e-element-25&quot; data-slate-node=&quot;element&quot;&gt;&lt;span id=&quot;w-e-text-18&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt; Apache Doris 是一款开源、分布式、MPP 架构的 OLAP（在线分析型）数据库&lt;/span&gt;&lt;/span&gt;&lt;span id=&quot;w-e-text-19&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt;，主打&lt;/span&gt;&lt;/span&gt;&lt;span id=&quot;w-e-text-20&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt;海量数据实时多维分析、秒级 / 亚秒级查询、高并发报表与即席查询&lt;/span&gt;&lt;/span&gt;&lt;span id=&quot;w-e-text-21&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt;，非常适合构建&lt;/span&gt;&lt;/span&gt;&lt;span id=&quot;w-e-text-22&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt;实时数据仓库、BI 看板、用户行为分析、日志分析、湖仓融合&lt;/span&gt;&lt;/span&gt;&lt;span id=&quot;w-e-text-23&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt;等场景。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p id=&quot;w-e-element-32&quot; data-slate-node=&quot;element&quot;&gt;&lt;span id=&quot;w-e-text-27&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt; 需要将数据从一台doris集群迁移到另一台doris服务器中，以下是操作步骤&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;h2 id=&quot;w-e-element-33&quot; data-slate-node=&quot;element&quot;&gt;&lt;span id=&quot;w-e-text-34&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt; 一、迁移表结构&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p id=&quot;w-e-element-37&quot; data-slate-node=&quot;element&quot;&gt;&lt;span id=&quot;w-e-text-36&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt; 首先将数据库导出sql文件。在一台可以连接doris的linux服务器上执行以下命令&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre class=&quot;brush:bash;toolbar:false;&quot;&gt;mysqldump&amp;nbsp;-h192.168.1.10&amp;nbsp;-P9030&amp;nbsp;-uroot&amp;nbsp;-p&amp;nbsp;\
--no-tablespaces&amp;nbsp;\
--no-data&amp;nbsp;\
--skip-column-statistics&amp;nbsp;\
--databases&amp;nbsp;test_db&amp;nbsp;\
&amp;gt;&amp;nbsp;doris_ok.sql&lt;/pre&gt;&lt;p id=&quot;w-e-element-59&quot; data-slate-node=&quot;element&quot;&gt;&lt;span id=&quot;w-e-text-49&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt; 接下来需要借助一点点AI的力量，把导出的文件交给AI，让它把sql修改成兼容doris数据库的语法，并且支持单个节点doris的（我这里新的doris是单节点的所以这么改，按照实际情况修改提示词），我使用的claude模型，效果比较好，一次就成功了，也可以使用国内模型试试。修改完后的代码保存成sql文件。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p id=&quot;w-e-element-68&quot; data-slate-node=&quot;element&quot;&gt;&lt;span id=&quot;w-e-text-61&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt;最后执行以下命令，导入到新库中&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre class=&quot;brush:bash;toolbar:false;&quot;&gt;mysql&amp;nbsp;-h192.168.1.45&amp;nbsp;-P9030&amp;nbsp;-uroot&amp;nbsp;-p&amp;nbsp;&amp;lt;&amp;nbsp;doris_fixed.sql&lt;/pre&gt;&lt;p id=&quot;w-e-element-69&quot; data-slate-node=&quot;element&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;h2 id=&quot;w-e-element-70&quot; data-slate-node=&quot;element&quot;&gt;&lt;span id=&quot;w-e-text-71&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt;二、同步数据&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;&lt;p id=&quot;w-e-element-79&quot; data-slate-node=&quot;element&quot;&gt;&lt;span id=&quot;w-e-text-78&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt;同步数据需要借助doris的CATALOG。“外部数据源的统一入口和命名空间”&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p id=&quot;w-e-element-86&quot; data-slate-node=&quot;element&quot;&gt;&lt;span id=&quot;w-e-text-82&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt;它的作用是让 Doris 不只是查询自己内部的数据，还能像一个“数据中台”一样，直接访问 Hive、Iceberg、Hudi、MySQL、PostgreSQL、Elasticsearch 等外部数据源。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p id=&quot;w-e-element-95&quot; data-slate-node=&quot;element&quot;&gt;&lt;span id=&quot;w-e-text-88&quot; data-slate-node=&quot;text&quot;&gt;&lt;span data-slate-leaf=&quot;true&quot;&gt;在新doris库中执行以下命令，将旧库作为外部数据库连接到doris中。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre class=&quot;brush:sql;toolbar:false;&quot;&gt;CREATE&amp;nbsp;CATALOG&amp;nbsp;doris_source&amp;nbsp;PROPERTIES&amp;nbsp;(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;type&amp;quot;&amp;nbsp;=&amp;nbsp;&amp;quot;jdbc&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;user&amp;quot;&amp;nbsp;=&amp;nbsp;&amp;quot;root&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;password&amp;quot;&amp;nbsp;=&amp;nbsp;&amp;quot;mysql.7334453&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;jdbc_url&amp;quot;&amp;nbsp;=&amp;nbsp;&amp;quot;jdbc:mysql://192.168.1.10:9030/&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;driver_url&amp;quot;&amp;nbsp;=&amp;nbsp;&amp;quot;https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.25/mysql-connector-java-8.0.25.jar&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;driver_class&amp;quot;&amp;nbsp;=&amp;nbsp;&amp;quot;com.mysql.cj.jdbc.Driver&amp;quot;
);&lt;/pre&gt;&lt;p&gt;执行&lt;/p&gt;&lt;pre class=&quot;brush:sql;toolbar:false;&quot;&gt;SHOW&amp;nbsp;CATALOGS;&lt;/pre&gt;&lt;p&gt;看到以下doris_source，表示已经连接成功。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/05/20260515091525177880772535964.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;然后就可以像操作一个数据库的方式导入数据了&lt;/p&gt;&lt;pre class=&quot;brush:sql;toolbar:false;&quot;&gt;INSERT&amp;nbsp;INTO&amp;nbsp;hx_theme_data.t_license
SELECT&amp;nbsp;*&amp;nbsp;FROM&amp;nbsp;doris_source.hx_theme_data.t_license&lt;/pre&gt;&lt;p&gt;运行以下sql生成所有需要导入表sql。&lt;/p&gt;&lt;pre class=&quot;brush:sql;toolbar:false;&quot;&gt;SELECT&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CONCAT(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;INSERT&amp;nbsp;INTO&amp;nbsp;hx_theme_data.`&amp;#39;,&amp;nbsp;TABLE_NAME,&amp;nbsp;&amp;#39;`&amp;nbsp;&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;SELECT&amp;nbsp;*&amp;nbsp;FROM&amp;nbsp;doris_source.hx_theme_data.`&amp;#39;,&amp;nbsp;TABLE_NAME,&amp;nbsp;&amp;#39;`;&amp;#39;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)&amp;nbsp;AS&amp;nbsp;sync_sql
FROM&amp;nbsp;information_schema.TABLES
WHERE&amp;nbsp;TABLE_SCHEMA&amp;nbsp;=&amp;nbsp;&amp;#39;hx_theme_data&amp;#39;
&amp;nbsp;&amp;nbsp;AND&amp;nbsp;TABLE_TYPE&amp;nbsp;=&amp;nbsp;&amp;#39;BASE&amp;nbsp;TABLE&amp;#39;;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/05/20260515091759177880787975256.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;直接复制所有sql运行就可以导入全部数据了。&lt;/p&gt;&lt;p id=&quot;w-e-element-96&quot; data-slate-node=&quot;element&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p id=&quot;w-e-element-99&quot; data-slate-node=&quot;element&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p id=&quot;w-e-element-102&quot; data-slate-node=&quot;element&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p id=&quot;w-e-element-105&quot; data-slate-node=&quot;element&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p id=&quot;w-e-element-106&quot; data-slate-node=&quot;element&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p id=&quot;w-e-element-73&quot; data-slate-node=&quot;element&quot;&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Fri, 15 May 2026 09:14:47 +0800</pubDate></item><item><title>千万别用sql查询经纬度数据了，有更快的方式</title><link>https://forstyle.cc/zblog/post/116.html</link><description>&lt;p&gt;最近需要查询学校周边的零售户有哪些，几千个学校，几十万零售户，用sql查询费了十几分钟才查询出来，后来问的AI，使用python代码，十几秒就能搞定。以下是完整的代码，可以作为参考。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/05/20260509174711177832003193716.png&quot; /&gt;&lt;/p&gt;
&lt;pre class=&quot;language-markup&quot;&gt;&lt;code&gt;def aaaaa():
    import numpy as np
    import pandas as pd
    from sklearn.neighbors import BallTree
    from time import time
    # 1. 从 Doris 读取数据
    from sqlalchemy import create_engine
    engine = create_engine(
        &quot;mysql+pymysql://root:mysql.7334453@192.168.1.10:9030/hx_theme_data?charset=utf8mb4&quot;
    )
    start_time = time()
    merchants = pd.read_sql(&quot;&quot;&quot;
        SELECT retailer_uuid, label_ids, label_names, company_name,
               label_list_fields, lic_no,
               CAST(latitude AS DOUBLE) AS lat_d,
               CAST(longitude AS DOUBLE) AS lng_d
        FROM t_license
        WHERE longitude IS NOT NULL AND longitude != 0
          AND latitude  IS NOT NULL AND latitude  != 0
          AND lic_status IN (&#039;01&#039;,&#039;02&#039;,&#039;10&#039;)
    &quot;&quot;&quot;, engine)

    schools = pd.read_sql(&quot;&quot;&quot;
        SELECT name, type,
               CAST(lat AS DOUBLE) AS lat_d,
               CAST(lng AS DOUBLE) AS lng_d
        FROM t_data_school_info
        WHERE lat IS NOT NULL AND lat != &#039;&#039; AND lat != &#039;0&#039;
          AND lng IS NOT NULL AND lng != &#039;&#039; AND lng != &#039;0&#039;
    &quot;&quot;&quot;, engine)

    # 2. 构建 BallTree（使用弧度，haversine 距离）
    school_coords = np.radians(schools[[&#039;lat_d&#039;, &#039;lng_d&#039;]].values)
    tree = BallTree(school_coords, metric=&#039;haversine&#039;)

    # 3. 批量查询每个商家最近的学校，距离阈值 200m
    merchant_coords = np.radians(merchants[[&#039;lat_d&#039;, &#039;lng_d&#039;]].values)
    DISTANCE_M = 200
    EARTH_RADIUS = 6371000

    distances, indices = tree.query(merchant_coords, k=1)  # 找最近1所
    distances_m = distances[:, 0] * EARTH_RADIUS           # 转换为米

    # 4. 过滤距离 &amp;lt; 200m 的结果
    mask = distances_m &amp;lt; DISTANCE_M
    result = merchants[mask].copy()
    result[&#039;distance&#039;]   = distances_m[mask]
    result[&#039;school_name&#039;] = schools.iloc[indices[mask, 0]][&#039;name&#039;].values
    result[&#039;school_type&#039;] = schools.iloc[indices[mask, 0]][&#039;type&#039;].values
    result[&#039;school_lat&#039;]  = schools.iloc[indices[mask, 0]][&#039;lat_d&#039;].values
    result[&#039;school_lng&#039;]  = schools.iloc[indices[mask, 0]][&#039;lng_d&#039;].values

    # 5. 结果写回 Doris
    # result.to_sql(&#039;t_merchant_nearest_school&#039;, engine, if_exists=&#039;replace&#039;)
    print(f&quot;耗时 {time() - start_time:.2f} 秒&quot;)
    print(f&quot;找到 {len(result)} 个200m内有学校的商家&quot;)&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Sat, 09 May 2026 17:27:05 +0800</pubDate></item><item><title>Django + Doris CRC32 分表实战：问题汇总与解决方案</title><link>https://forstyle.cc/zblog/post/115.html</link><description>&lt;blockquote&gt;
&lt;p&gt;一次从零到一的 Django 分表实践，记录踩过的所有坑&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;h2-u524Du8A00&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;/h2&gt;&lt;p&gt;最近在做一个零售户管理系统，需要处理十亿级的数据。考虑到 Doris 的强大分析能力，使用 Doris 作为数据库，并基于 CRC32 算法实现自动分表。过程并不顺利，遇到了各种各样的问题。记录这些问题及解决方案，希望能帮助到有类似需求的开发者。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/05/202605061637497499847.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;h3--1-doris-&quot;&gt;&lt;a name=&quot;问题1：Doris 数据库连接失败&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：Doris 数据库连接失败&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;错误信息：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;django.db.utils.OperationalError: (2003, &amp;quot;Can&amp;#39;t connect to MySQL server on &amp;#39;xxx&amp;#39;&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;问题原因：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Doris 使用 MySQL 协议，但端口不是默认的 3306&lt;/li&gt;&lt;li&gt;防火墙未开放 Doris 端口&lt;/li&gt;&lt;li&gt;未安装 PyMySQL 驱动&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;解决方案：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# settings.py
DATABASES = {
    &amp;#39;doris&amp;#39;: {
        &amp;#39;ENGINE&amp;#39;: &amp;#39;django.db.backends.mysql&amp;#39;,
        &amp;#39;NAME&amp;#39;: &amp;#39;your_database&amp;#39;,
        &amp;#39;USER&amp;#39;: &amp;#39;your_user&amp;#39;,
        &amp;#39;PASSWORD&amp;#39;: &amp;#39;your_password&amp;#39;,
        &amp;#39;HOST&amp;#39;: &amp;#39;your_doris_host&amp;#39;,
        &amp;#39;PORT&amp;#39;: &amp;#39;9030&amp;#39;,  # Doris 默认 MySQL 协议端口
        &amp;#39;OPTIONS&amp;#39;: {
            &amp;#39;init_command&amp;#39;: &amp;quot;SET sql_mode=&amp;#39;STRICT_TRANS_TABLES&amp;#39;&amp;quot;,
            &amp;#39;charset&amp;#39;: &amp;#39;utf8mb4&amp;#39;,
        },
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;关键点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Doris 的 MySQL 协议端口通常是 9030（不是 3306）&lt;/li&gt;&lt;li&gt;需要安装 &lt;code&gt;pymysql&lt;/code&gt;：&lt;code&gt;pip install pymysql&lt;/code&gt;&lt;/li&gt;&lt;li&gt;在 &lt;code&gt;__init__.py&lt;/code&gt; 中添加：&lt;code&gt;import pymysql; pymysql.install_as_MySQLdb()&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;h3--2-nameerror-name-baselicense-is-not-defined&quot;&gt;&lt;a name=&quot;问题2：NameError: name ‘BaseLicense’ is not defined&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：NameError: name ‘BaseLicense’ is not defined&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;错误信息：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;NameError: name &amp;#39;BaseLicense&amp;#39; is not defined&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;问题原因：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 &lt;code&gt;router.py&lt;/code&gt; 中使用了 &lt;code&gt;BaseLicense&lt;/code&gt; 但没有导入或定义&lt;/li&gt;&lt;li&gt;模型定义顺序导致引用问题&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;解决方案：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;方案一：在 router.py 中定义（简单但不推荐）&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# router.py
class BaseLicense(models.Model):
    class Meta:
        abstract = True&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;方案二：分离模型和路由逻辑（推荐）&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# models.py
class BaseLicense(models.Model):
    # 字段定义...
    class Meta:
        abstract = True

# router.py
from .models import BaseLicense  # 正确导入&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;最佳实践：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;将所有模型定义在 &lt;code&gt;models.py&lt;/code&gt; 中&lt;/li&gt;&lt;li&gt;路由逻辑单独放在 &lt;code&gt;router.py&lt;/code&gt; 或 &lt;code&gt;shard_router.py&lt;/code&gt;&lt;/li&gt;&lt;li&gt;使用明确的导入路径&lt;/li&gt;&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;h3--3-no-such-table-t_license_8&quot;&gt;&lt;a name=&quot;问题3：no such table: t_license_8&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：no such table: t_license_8&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;错误信息：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;django.db.utils.OperationalError: no such table: t_license_8&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;问题原因：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Django 默认使用 &lt;code&gt;default&lt;/code&gt; 数据库连接&lt;/li&gt;&lt;li&gt;&lt;code&gt;default&lt;/code&gt; 配置的是 SQLite，但实际表在 Doris 中&lt;/li&gt;&lt;li&gt;未指定使用 Doris 数据库&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;解决方案：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;方案一：每次查询指定数据库（简单直接）&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;result = model.objects.using(&amp;#39;doris&amp;#39;).get(lic_no=lic_no)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;方案二：配置数据库路由器（优雅）&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# db_router.py
class DorisRouter:
    def db_for_read(self, model, **hints):
        if model.__name__.startswith(&amp;#39;License_&amp;#39;):
            return &amp;#39;doris&amp;#39;
        return None

# settings.py
DATABASE_ROUTERS = [&amp;#39;your_app.db_router.DorisRouter&amp;#39;]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;知识点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;using()&lt;/code&gt; 方法用于指定数据库&lt;/li&gt;&lt;li&gt;数据库路由器可以实现自动化路由&lt;/li&gt;&lt;li&gt;记得在 settings 中注册路由器&lt;/li&gt;&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;h3--4-unknown-column-id-in-t_license_8-&quot;&gt;&lt;a name=&quot;问题4：Unknown column ‘id’ in ‘t_license_8’&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;问题4：Unknown column ‘id’ in ‘t_license_8’&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;错误信息：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;django.db.utils.OperationalError: (1054, &amp;quot;errCode = 2, detailMessage = Unknown column &amp;#39;id&amp;#39; in &amp;#39;t_license_8&amp;#39;&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;问题原因：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Django 模型默认会自动添加一个名为 &lt;code&gt;id&lt;/code&gt; 的自增主键字段&lt;/li&gt;&lt;li&gt;Doris 表使用 &lt;code&gt;retailer_uuid&lt;/code&gt; 作为主键，没有 &lt;code&gt;id&lt;/code&gt; 字段&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;解决方案：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class BaseLicense(models.Model):
    # ✅ 必须明确指定主键字段
    retailer_uuid = models.CharField(
        max_length=96, 
        primary_key=True,  # 关键：指定为主键
        verbose_name=&amp;#39;零售户UUID&amp;#39;
    )
    lic_no = models.CharField(max_length=60, null=True)
    # ... 其他字段

    class Meta:
        abstract = True
        managed = False  # 禁止 Django 管理表结构&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;关键点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;必须用 &lt;code&gt;primary_key=True&lt;/code&gt; 标记主键字段&lt;/li&gt;&lt;li&gt;设置 &lt;code&gt;managed = False&lt;/code&gt; 避免 Django 尝试创建/修改表&lt;/li&gt;&lt;li&gt;&lt;code&gt;abstract = True&lt;/code&gt; 让基类不创建实际表&lt;/li&gt;&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;h3--5-object-of-type-license_t_license_8-is-not-json-serializable&quot;&gt;&lt;a name=&quot;问题5：Object of type License_t_license_8 is not JSON serializable&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;问题5：Object of type License_t_license_8 is not JSON serializable&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;错误信息：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TypeError: Object of type License_t_license_8 is not JSON serializable&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;问题原因：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Django ORM 返回的是模型对象，不是字典&lt;/li&gt;&lt;li&gt;JSON 序列化器无法处理 Django 模型实例&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;解决方案对比：&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;方案&lt;/th&gt;
&lt;th&gt;代码&lt;/th&gt;
&lt;th&gt;优点&lt;/th&gt;
&lt;th&gt;缺点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;使用 values()&lt;/td&gt;
&lt;td&gt;&lt;code&gt;model.objects.filter().values().first()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;直接返回字典，性能好&lt;/td&gt;
&lt;td&gt;返回的是字典，不是模型实例&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;使用 model_to_dict&lt;/td&gt;
&lt;td&gt;&lt;code&gt;model_to_dict(obj)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;可转换已有模型实例&lt;/td&gt;
&lt;td&gt;需要先获取实例&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;手动构建字典&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{&amp;#39;field&amp;#39;: obj.field}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;完全可控&lt;/td&gt;
&lt;td&gt;代码冗长&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;使用 Django 序列化器&lt;/td&gt;
&lt;td&gt;&lt;code&gt;serializers.serialize(&amp;#39;json&amp;#39;, queryset)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;功能完整&lt;/td&gt;
&lt;td&gt;返回格式特殊&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;推荐方案：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 方案一：直接使用 values()（推荐）
@router.get(&amp;quot;/license&amp;quot;)
def get_license(request, lic_no: str):
    model = get_model_for_license(lic_no)
    result = model.objects.using(&amp;#39;doris&amp;#39;).filter(
        lic_no=lic_no
    ).values().first()  # 直接返回字典
    return result

# 方案二：使用 model_to_dict
from django.forms.models import model_to_dict

@router.get(&amp;quot;/license&amp;quot;)
def get_license(request, lic_no: str):
    model = get_model_for_license(lic_no)
    obj = model.objects.using(&amp;#39;doris&amp;#39;).get(lic_no=lic_no)
    return model_to_dict(obj)  # 转换为字典&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
</description><pubDate>Wed, 06 May 2026 16:32:46 +0800</pubDate></item><item><title>一键删除**所有**Anaconda虚拟环境（安全、干净、彻底）</title><link>https://forstyle.cc/zblog/post/114.html</link><description>&lt;p&gt;&lt;strong&gt;最安全、最简单、直接清空所有环境&lt;/strong&gt;的方法，不用一个个删，也不会弄坏你的 base 环境。&lt;br&gt;&lt;img src=&quot;https://forstyle.cc/zblog/zb_users/upload/2026/04/202604271659364097709.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;h2--&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;/h2&gt;&lt;p&gt;先打开 &lt;strong&gt;Anaconda Prompt&lt;/strong&gt;（Windows）或 &lt;strong&gt;终端&lt;/strong&gt;（Mac/Linux），执行：&lt;/p&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-bash&quot;&gt;conda env list&lt;/code&gt;&lt;/pre&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;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;for /f &amp;quot;skip=1 tokens=1&amp;quot; %i in (&amp;#39;conda env list ^| findstr /v &amp;quot;base&amp;quot;&amp;#39;) do conda remove -n %i --all -y&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;上面这行是 Windows 专用命令，直接复制粘贴运行即可。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;运行后它会&lt;strong&gt;自动逐个删除所有非 base 的环境&lt;/strong&gt;，全程不需要你手动确认。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;h2-mac-linux-&quot;&gt;&lt;a name=&quot;Mac / Linux 系统用这个命令&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;Mac / Linux 系统用这个命令&lt;/h2&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;conda env list | grep -v &amp;#39;base&amp;#39; | awk &amp;#39;{print $1}&amp;#39; | xargs -I {} conda remove -n {} --all -y&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;h2-u91CDu8981u63D0u9192&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;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;不会删除 base 环境&lt;/strong&gt;（你的 Anaconda 本体不会坏）&lt;/li&gt;&lt;li&gt;&lt;strong&gt;不会删除 Anaconda 软件&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;只删除你自己创建的所有虚拟环境&lt;/li&gt;&lt;li&gt;删完后执行 &lt;code&gt;conda env list&lt;/code&gt;，只会剩下 &lt;code&gt;base&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;h2--&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;/h2&gt;&lt;p&gt;环境删完后，再运行这个清理缓存，能多出几个G空间：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;conda clean -a -y&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-u603Bu7ED3&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;ol&gt;
&lt;li&gt;Windows 用我给的 &lt;strong&gt;for /f&lt;/strong&gt; 命令一键清空所有环境&lt;/li&gt;&lt;li&gt;Mac/Linux 用对应的 bash 一键清空&lt;/li&gt;&lt;li&gt;最后用 &lt;code&gt;conda clean -a -y&lt;/code&gt; 彻底清理&lt;/li&gt;&lt;li&gt;全程安全、不会损坏 Anaconda&lt;/li&gt;&lt;/ol&gt;
</description><pubDate>Mon, 27 Apr 2026 16:52:44 +0800</pubDate></item><item><title>Django 操作 Redis 完整教程</title><link>https://forstyle.cc/zblog/post/113.html</link><description>&lt;p&gt;Redis 是一款高性能的内存数据库，Django 中常用来做&lt;strong&gt;缓存、会话存储、计数器、消息队列&lt;/strong&gt;等。下面我带你从&lt;strong&gt;安装配置 → 基础使用 → 高级操作&lt;/strong&gt;完整掌握 Django 操作 Redis 的方法。&lt;/p&gt;
&lt;h2 id=&quot;h2--&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;/h2&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;Django 操作 Redis 最常用的库是 &lt;code&gt;django-redis&lt;/code&gt;（官方推荐）：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pip install django-redis redis&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-2-redis&quot;&gt;&lt;a name=&quot;2. 本地/服务器启动 Redis&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. 本地/服务器启动 Redis&lt;/h3&gt;&lt;p&gt;确保你的设备已经安装并启动了 Redis 服务：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windows：下载 Redis 安装包，启动 &lt;code&gt;redis-server.exe&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Mac/Linux：&lt;code&gt;brew install redis&lt;/code&gt; 或 &lt;code&gt;apt install redis-server&lt;/code&gt;，执行 &lt;code&gt;redis-server&lt;/code&gt; 启动&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;h2--django-redis&quot;&gt;&lt;a name=&quot;二、Django 配置 Redis&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;二、Django 配置 Redis&lt;/h2&gt;&lt;p&gt;打开项目的 &lt;code&gt;settings.py&lt;/code&gt;，添加以下配置：&lt;/p&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-python&quot;&gt;# settings.py

# 配置 Redis 为缓存后端
CACHES = {
    &amp;quot;default&amp;quot;: {
        &amp;quot;BACKEND&amp;quot;: &amp;quot;django_redis.cache.RedisCache&amp;quot;,
        # Redis 地址：格式 redis://:密码@主机:端口/数据库编号
        # 无密码：redis://127.0.0.1:6379/1
        &amp;quot;LOCATION&amp;quot;: &amp;quot;redis://127.0.0.1:6379/1&amp;quot;,
        &amp;quot;OPTIONS&amp;quot;: {
            &amp;quot;CLIENT_CLASS&amp;quot;: &amp;quot;django_redis.client.DefaultClient&amp;quot;,
            # 连接池配置（优化性能）
            &amp;quot;CONNECTION_POOL_KWARGS&amp;quot;: {&amp;quot;max_connections&amp;quot;: 100}
        }
    }
}

# 可选：将 Django 会话存储到 Redis
SESSION_ENGINE = &amp;quot;django.contrib.sessions.backends.cache&amp;quot;
SESSION_CACHE_ALIAS = &amp;quot;default&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2--&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;/h2&gt;&lt;p&gt;&lt;code&gt;django-redis&lt;/code&gt; 封装了 Django 原生缓存 API，&lt;strong&gt;无需手动连接 Redis&lt;/strong&gt;，直接调用即可。&lt;/p&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-python&quot;&gt;from django.core.cache import cache&lt;/code&gt;&lt;/pre&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;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 1. 设置缓存（key, value, 过期时间/秒）
cache.set(&amp;quot;username&amp;quot;, &amp;quot;zhangsan&amp;quot;, timeout=60)  # 60秒后过期
cache.set(&amp;quot;age&amp;quot;, 20)  # 不写timeout：永久有效

# 2. 获取缓存
name = cache.get(&amp;quot;username&amp;quot;)  # 存在返回值，不存在返回None
age = cache.get(&amp;quot;age&amp;quot;, 0)  # 不存在时返回默认值0

# 3. 删除缓存
cache.delete(&amp;quot;username&amp;quot;)  # 删除指定key
cache.clear()  # 清空当前数据库所有缓存（谨慎使用！）

# 4. 判断key是否存在
cache.has_key(&amp;quot;username&amp;quot;)

# 5. 自增/自减（适合做计数器、点赞数）
cache.set(&amp;quot;view_count&amp;quot;, 0)
cache.incr(&amp;quot;view_count&amp;quot;)  # +1 → 1
cache.incr(&amp;quot;view_count&amp;quot;, 5)  # +5 → 6
cache.decr(&amp;quot;view_count&amp;quot;)  # -1 → 5&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2--redis-&quot;&gt;&lt;a name=&quot;四、直接操作原生 Redis 命令（进阶）&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;四、直接操作原生 Redis 命令（进阶）&lt;/h2&gt;&lt;p&gt;Django 封装的 API 不够用时，可以&lt;strong&gt;获取原生 Redis 连接&lt;/strong&gt;，执行 Redis 所有原生命令（哈希、列表、集合等）。&lt;/p&gt;
&lt;h3 id=&quot;h3-1-redis-&quot;&gt;&lt;a name=&quot;1. 获取原生 Redis 客户端&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. 获取原生 Redis 客户端&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from django_redis import get_redis_connection

# 获取连接（使用settings.py中配置的default连接）
redis_conn = get_redis_connection(&amp;quot;default&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;h3-2-redis-&quot;&gt;&lt;a name=&quot;2. 原生 Redis 常用操作&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. 原生 Redis 常用操作&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 字符串
redis_conn.set(&amp;quot;name&amp;quot;, &amp;quot;lisi&amp;quot;)
print(redis_conn.get(&amp;quot;name&amp;quot;).decode())  # 二进制转字符串

# 哈希（适合存储对象）
redis_conn.hset(&amp;quot;user:1&amp;quot;, &amp;quot;name&amp;quot;, &amp;quot;wangwu&amp;quot;)
redis_conn.hset(&amp;quot;user:1&amp;quot;, &amp;quot;age&amp;quot;, 25)
print(redis_conn.hgetall(&amp;quot;user:1&amp;quot;))  # 获取所有字段

# 列表
redis_conn.lpush(&amp;quot;task_list&amp;quot;, &amp;quot;任务1&amp;quot;)
redis_conn.rpush(&amp;quot;task_list&amp;quot;, &amp;quot;任务2&amp;quot;)
print(redis_conn.lrange(&amp;quot;task_list&amp;quot;, 0, -1))  # 获取所有元素

# 设置过期时间
redis_conn.expire(&amp;quot;user:1&amp;quot;, 300)  # 5分钟后过期

# 删除key
redis_conn.delete(&amp;quot;name&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2--django-redis&quot;&gt;&lt;a name=&quot;五、实战：Django 视图中使用 Redis&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;五、实战：Django 视图中使用 Redis&lt;/h2&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;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# views.py
from django.shortcuts import render
from django.core.cache import cache

def article_detail(request, article_id):
    # 浏览量key
    view_key = f&amp;quot;article:{article_id}:views&amp;quot;

    # 自增浏览量
    cache.incr(view_key)

    # 获取浏览量
    view_count = cache.get(view_key, 0)

    return render(request, &amp;quot;article.html&amp;quot;, {&amp;quot;views&amp;quot;: view_count})&lt;/code&gt;&lt;/pre&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;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def hot_articles(request):
    # 先从缓存取
    hot_list = cache.get(&amp;quot;hot_article_list&amp;quot;)

    # 缓存不存在，查询数据库并写入缓存
    if not hot_list:
        hot_list = Article.objects.filter(is_hot=True)
        cache.set(&amp;quot;hot_article_list&amp;quot;, hot_list, timeout=60*10)  # 缓存10分钟

    return render(request, &amp;quot;hot.html&amp;quot;, {&amp;quot;articles&amp;quot;: hot_list})&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;h2--&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;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;缓存页面/数据&lt;/strong&gt;：减少数据库压力，提升响应速度&lt;/li&gt;&lt;li&gt;&lt;strong&gt;会话存储&lt;/strong&gt;：&lt;code&gt;SESSION_ENGINE&lt;/code&gt; 配置后，Django 会话自动存在 Redis&lt;/li&gt;&lt;li&gt;&lt;strong&gt;计数器&lt;/strong&gt;：点赞数、浏览量、签到统计（&lt;code&gt;incr&lt;/code&gt; 命令）&lt;/li&gt;&lt;li&gt;&lt;strong&gt;分布式锁&lt;/strong&gt;：解决高并发下的数据安全问题&lt;/li&gt;&lt;li&gt;&lt;strong&gt;消息队列&lt;/strong&gt;：配合 celery 做异步任务&lt;/li&gt;&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;h3-u603Bu7ED3&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;ol&gt;
&lt;li&gt;安装：&lt;code&gt;pip install django-redis redis&lt;/code&gt;&lt;/li&gt;&lt;li&gt;配置：&lt;code&gt;settings.py&lt;/code&gt; 中配置 &lt;code&gt;CACHES&lt;/code&gt;&lt;/li&gt;&lt;li&gt;简单使用：&lt;code&gt;from django.core.cache import cache&lt;/code&gt; 调用封装方法&lt;/li&gt;&lt;li&gt;高级使用：&lt;code&gt;get_redis_connection()&lt;/code&gt; 获取原生连接，执行所有 Redis 命令&lt;/li&gt;&lt;li&gt;核心用途：缓存、计数器、会话、高并发优化&lt;/li&gt;&lt;/ol&gt;
</description><pubDate>Sat, 25 Apr 2026 09:21:59 +0800</pubDate></item></channel></rss>