Friday, August 20, 2021

V2EX - 技术

V2EX - 技术


Windows 一分钟使用 C++ 发送 Http 请求

Posted: 20 Aug 2021 04:56 AM PDT

有人说 c++ 发 http 请求麻烦,我不太认同,我认为一分钟内能搞定的事情,无论如何也谈不上"麻烦"
为了帮助后来人,方便以后英文不太好,常使用中文搜索的同学找到答案,我单独发到这里

1. VS 新建一个 Cpp console 工程,工程右键 -> Manage nuget packager
2. 搜索 cpprestsdk,并 点击 install

3. 复制以下代码替换 main.cpp ,然后 F5

#include <iostream>
#include <cpprest/http_client.h>
int main()
{
web::http::client::http_client client(U("https://postman-echo.com/get?a=b"));
auto rsp = client.request(web::http::methods::GET).get();
auto body = rsp.extract_string().get();
std::wcout << rsp.status_code() << "\n" << body << std::endl;
}


全程录屏:

SEO Area:
C++ 发 http 请求
Cpp 发 http 请求
怎么用 Cpp 发 http 请求
http 请求 cpp
http 请求 c++

go 程序员, 第二门语言选择 c++ 还是 rust?

Posted: 20 Aug 2021 04:54 AM PDT

gopher, 会一些 python 。第二门语言在学一个后端语言,还是学前端搞全栈

有被 systemd-resolved 服务烦到的兄弟吗

Posted: 20 Aug 2021 04:46 AM PDT

你们一般怎么设置 dns 服务,并且禁掉这个服务。

RSS 客户端应该像一个流一样

Posted: 20 Aug 2021 04:30 AM PDT

RSS 客户端应该把不同 RSS 源的信息合并成一个流,而且:
不允许重复查看
只允许按时间顺序查看
不允许按不同 RSS 源查看
全自动更新

harmony os 大家用的感觉怎么样

Posted: 20 Aug 2021 04:30 AM PDT

工作中该怎么改 bug??

Posted: 20 Aug 2021 04:21 AM PDT

代码出现了一些 bug (代码由不同的人,不同的任务堆积成) 现在需要修复这个 bug 。bug 原因是其他人的代码没考虑周全造成的

第一种: 找到这个没考虑周全的点 并且打补丁修复它 也不影响到其他的地方 bug 修复好 第二种:修复其他人任务的代码 然后修复好 bug

1 和 2 的主要区别是在修改的 bug 的同时去优化别人的代码

使用哪种方式更好?

洋葱浏览器不能装插件,那谷歌浏览器有洋葱插件吗

Posted: 20 Aug 2021 03:49 AM PDT

windows installer 为什么一直给我弹窗啊?如何才能关闭?

Posted: 20 Aug 2021 03:46 AM PDT

名称为 windows installer 的弹窗

本人已尝试如下方法去关闭:

  1. 关闭 windows installer 的 windows 服务,无用
  2. 找到 windows installer 关联的 windows 服务并关闭,也无用

烦死了,关闭了弹窗,过一分钟就会再弹,大家有什么办法可以解决吗?

实在不行我就只能把这个弹窗对应的 exe 执行文件替换了。。但是又担心有什么问题,这个文件路径如下:

C:\Windows\SysWOW64\msiexec 

wiki 说这个玩意儿还挺重要的,不太好操作,头大。

描述一下这个弹窗,就是一个正常的 windows 弹窗,内部存在一个 textview,其中的消息如下:

Windows ® Installer. V 5.0.19041.1  msiexec /Option <Required Parameter> [Optional Parameter]  安装选项  </package | /i> <Product.msi>  安装或配置产品  /a <Product.msi>  管理安装 - 在网络上安装产品  /j<u|m> <Product.msi> [/t <Transform List>] [/g <Language ID>]  公布产品 - m 公布到所有用户,u 公布到当前用户  </uninstall | /x> <Product.msi | ProductCode>  卸载产品 显示选项  /quiet  安静模式,无用户交互  /passive  无人参与模式 - 只显示进度栏  /q[n|b|r|f]  设置用户界面级别  n - 无用户界面  b - 基本界面  r - 精简界面  f - 完整界面(默认值)  /help  帮助信息 重新启动选项  /norestart  安装完成后不重新启动  /promptrestart  必要时提示用户重新启动  /forcerestart  安装后始终重新启动计算机 日志选项  /l[i|w|e|a|r|u|c|m|o|p|v|x|+|!|*] <LogFile>  i - 状态消息  w - 非致命警告  e - 所有错误消息  a - 操作的启动  r - 操作特定记录  u - 用户请求  c - 初始用户界面参数  m - 内存不足或致命退出信息  o - 磁盘空间不足消息  p - 终端属性  v - 详细输出  x - 额外调试信息  + - 扩展到现有日志文件  ! - 每一行刷新到日志  * - 记录所有信息,除了 v 和 x 选项  /log <LogFile>  与 /l* <LogFile> 相同 更新选项  /update <Update1.msp>[;Update2.msp]  应用更新  /uninstall <PatchCodeGuid>[;Update2.msp] /package <Product.msi | ProductCode>  删除产品的更新 修复选项  /f[p|e|c|m|s|o|d|a|u|v] <Product.msi | ProductCode>  修复产品  p - 仅当文件丢失时  o - 如果文件丢失或安装了更旧的版本(默认值)  e - 如果文件丢失或安装了相同或更旧的版本  d - 如果文件丢失或安装了不同版本  c - 如果文件丢失或较验和与计算的值不匹配  a - 强制重新安装所有文件  u - 所有必要的用户特定注册表项(默认值)  m - 所有必要的计算机特定注册表项(默认值)  s - 所有现有的快捷键方式(默认值)  v - 从源运行并重新缓存本地安装包 设置公共属性  [PROPERTY=PropertyValue]  请查阅 Windows (R) Installer SDK 获得有关 命令行语法的其他文档。  版权所有 (C) Microsoft Corporation. 保留所有权利。 此软件的部分内容系基于 Independent JPEG Group 的工作。  

大家有遇到过吗。。

在福报厂干外包,吐槽一下一些项目开发的乱象

Posted: 20 Aug 2021 03:36 AM PDT

众所周知,一般一个公司会有很多产品,一个产品背后的服务也不止一个,也就是说有一个产品背后对应着多个项目,在某福报厂,大大小小的项目数不胜数,基本上只要写个东西都要整一个单独的项目出来。

我有时候很好奇,为什么要搞那么多项目出来,但是仔细一想,整个新项目才有新 KPI 啊

这些大大小小的项目,有些可能只是几个接口,几个定时任务。。。所以也算不上很重要的,而且都是内部项目,并不是面向普通用户。所以也没有运维、测试等配套人员,只有你自己,基本上就是想咋搞就咋搞。

1.发布全靠手动。福报内部有一个叫作 aone 的容器化发布平台,但是配置繁杂,很多 p7 大佬也不会,或者懒的搞,直接就是打一个 rpm 包,然后 ssh 到生产服务器上面手动安装发布,写一个 shell 脚本保活就算完事。

2.看日志要到生产服务器上。话说但凡是一个项目少不了业务日志,出点问题的话总要看日志排查,但是呢,我所接触的项目很多都没有对接日志平台,类似 elk 这样的东西福报厂内部也有。但是很多 p7 大佬不知道是不会还是懒。有时候看个日志就 ssh 到服务器上面 tail 。但是外包狗是没有生产服务器权限的,所以你懂的。。。

3.数据库设计很烂。所谓的核心库,里面有几百张表,建表根本没有一个统一规范,或者是有规范但是没有人监督执行。有些表没有 id 主键,有些表是复合主键,表的时间字段有叫 time,有叫 utime,还有叫 gmt_created,还有叫 created_at,一个库里面这样的设计比比皆是。

更不要说什么数据库设计三范式了,我怀疑这些 p7 大佬们压根就不懂 mysql,其实也正常,因为他们大多数并不是主要搞 web 开发,对于他们来说,mysql 就是存个数据,也不用考虑性能问题。可是倒是苦了我们这些写 CRUD 的外包狗。

以上内容纯属虚构,如有雷同,纯属巧合!

想问下现在 2021 年 8 月还有人在用 WINDOWS 7 吗?

Posted: 20 Aug 2021 03:18 AM PDT

这几天突发奇想,重新买了块 SSD,专门用来安装 WINDOWS7 。

特别喜欢以前的毛玻璃特效。

这都 2021 年了,想知道还有人在用 WINDOWS 7 作为主系统吗??为什么??

Python3.5 版本应该如何快速搭建 web 服务?

Posted: 20 Aug 2021 03:15 AM PDT

如题,生产环境有一套嵌入式 python,基于 3.5 版本不能修改。想要通过 web 服务进行控制,而且最好不依赖第三方库,有什么代码可以快速实现一个基础的基于 http (或者 tcp )进行远程调用的服务吗?

csdn 这个登录后复制有插件处理吗?

Posted: 20 Aug 2021 03:09 AM PDT

我有装个叫"Enable Copy"的拓展,但好像对 csdn 无效了,

就搞不懂 csdn 对自己的用户群体有没点了解,这种纯恶心人的功能拿来做什么,

useConext or redux or 状态提升?

Posted: 20 Aug 2021 03:06 AM PDT

举例一个场景

上面是一堆的开关过滤器, 输出一堆参数给 Data 过滤 <FilterArea/> 下面是一个 table 展示数据 <DataArea/> 
  • 要么在 FilterArea 里面做状态提升
  • 要么在 FilterArea 里面做 useContext ?

这种会影响代码可读性吧,毕竟 FilterArea 比较偏 UI,可能写在各种表现形式上

  • 要么用 redux 写一大堆各种 types, actions, reducers

各位是用哪种?

有什么办法能在本地快速地把 pdf 分享到 web 服务中吗?

Posted: 20 Aug 2021 03:05 AM PDT

如题,需要阅读大量学术文献的时候,大部分是 pdf 格式的。

但是由于 chrome 默认打开 pdf 时不加载 js,导致自带的谷歌翻译,还有插件的划词工具都没法用,严重拖慢阅读速度。

有什么办法可以快速地把 pdf 放到网页上,然后让划词功能可以用吗?

Vue3 hooks 的问题

Posted: 20 Aug 2021 03:04 AM PDT

1 、因为很多页面都需要用到表格,所以我抽取了表格的逻辑到一个叫 useCommonTable.ts 的文件中,大概如下:

// ...省略无关代码 export default function (url) {    const isLoading = ref(false)    const tableData = ref([])    const commonTableConfig = reactive({      // ...    })        const getTableData = () => {    	 // ...    }        return {       isLoading,       tableData,       commonTableConfig,       getTableData    } } 

在使用的时候,一般就是如下:

setup() {   const {     isLoading,     tableData,     commonTableConfig,     getTableData   } = useCommonTable('url')      return {     isLoading,     tableData,     commonTableConfig,     getTableData   } } 

但是好死不死,突然有一个页面有 2 个表格,然后逻辑也一样,那我解构就重名了

setup() {   // 表格 1   const {     isLoading,     tableData,     commonTableConfig,     getTableData   } = useCommonTable('url1')   // 表格 2   const {     isLoading,     tableData,     commonTableConfig,     getTableData   } = useCommonTable('url2')      return {     isLoading,     tableData,     commonTableConfig,     getTableData   } } 

所以这种情况应该如何使用啊?我目前是

setup() {   // 表格 1   const useTable1 = useCommonTable('url1')   // 表格 2   const useTable2= useCommonTable('url2')      return {     isLoading1: useTable1.isLoading,     tableData1: useTable1.tableData,     commonTableConfig :useTable1.commonTableConfig,     getTableData1: useTable1.getTableData,     isLoading2: useTable2.isLoading,     tableData2: useTable2.tableData,     commonTableConfig :useTable1.commonTableConfig,     getTableData2: useTable2.getTableData   } } 

感觉这种导入方式有点啰里八嗦的。。。不知道各位大神是如何做的?能否教教小弟。。。

2 、关于 hooks 之间的调用

// hook1.ts export default function() {   const getStudentDetails = (studentId) => {     // ...   } }  // hook2.ts export default function() {   const getClassDetails = async () => {      const studentIds = await self.$axios.get('...')      // 这里希望调用 hook1.ts 中的方法      // getStudentDetails(studentIds[0])   } } 

如果使用 callback 方式,在 hook2.ts 中传入的话,会导致 setup 中的引入必须有先后关系:

setup() {   const {getStudentDetails} = useHook1()   const {getClassDetails} = useHook2(getStudentDetails)      return {     // ...   } } 

大哥们能教教小弟吗?新手勿喷,感谢大家!

Linux 重启网络服务为什么连接不会断

Posted: 20 Aug 2021 02:30 AM PDT

操作系统:centos 7,使用 systemctl restart networt 重启网络服务为什么 socket 连接不会断,比如 SSH 连接,抓包也没发现 TCP 有重连,请问这个机制是怎么实现的。

postgresql 的日期字段数据转成字符串,能不能设置日期默认转换字符串的格式?

Posted: 20 Aug 2021 02:15 AM PDT

postgresql 数据类型中,其中的三个日期类型,timestamp,date,time,这三个转成字符串,也就是格式化的时候,不指定转换格式。

Dbeaver 连接 pg 查询的结果集

查询会发生下面几种情况 timestamp 例:不加字符串转换结果:2021-08-18 16:09:56,加了字符串转换结果:2021-08-18 T16:09:56.256121

time 例:不加字符串转换结果:16:09:56,加了字符串转换结果:16:09:56.256121

date 的显示还算正常。

那能不能设置查询 timestamp 和 time 类型的列的结果集内容的默认格式化类型的配置

比如 timestamp 例:2021-08-18 16:09:56,默认格式化结果集格式为:2021-08-18 16:09

time 例:16:09:56,默认格式化结果集格式为:16:09

一种方式是给日期列的结果集内容加格式化函数,但这样每遇到一个日期字段,为了按照自己的要求显示指定日期格式,都得手动添加,这样会很麻烦

extX(X=2,3,4)等文件系统的数据盘也需要预留 5%的空间吗?

Posted: 20 Aug 2021 01:58 AM PDT

看了一些说法,如serverfault里面说的预留是为了即便系统盘空间打满后,系统的一些关键进程还能跑,比如 ssh 什么的。但是数据盘有必要预留这么大吗?尤其是比如 7 个 T 的盘要少将近 350G 的磁盘空间,感觉很亏啊!难道这个预留空间还有什么别的用途?还有个问题想请教一下,就是可以通过一个命令( tune2fs -m 0 /dev/foo_bar )优化这个空间,这个命令对 I/O 量很大的磁盘会产生性能抖动吗?

请教一下, TuSimple 这个公司美国办公室的 work life balance 咋样?

Posted: 20 Aug 2021 12:56 AM PDT

有了解的能否介绍一下,谢谢

SpringSecurity 有必要分两个用户表吗

Posted: 20 Aug 2021 12:45 AM PDT

背景: 多租户系统,区分了运维人员和租户用户表,区分是区分了,但是我做权限时,因为运维人员也需要角色和权限,租户用户也有,所以我就卡在了这里。
分两个是因为两个表的字段属性完全不同,只有一个共同点可能只剩个 ID,现在想想有必要分两个表吗,我新建了 permission 和 role 表,但现在他们两个表中的 user_id 边界变得超级模糊

mac m1 芯片电脑使用 idea,文件多次移动后产生问题

Posted: 20 Aug 2021 12:41 AM PDT

多次移动后发现,idea 卡顿,cup 使用率上升。其他应用没有问题,重启 idea 后恢复正常。只要不去碰文件移动,基本不会出现这个问题,不知道 v 友是怎么处理的……

有没有朋友需要游戏美术的

Posted: 20 Aug 2021 12:30 AM PDT

本人承接游戏美术设计,擅长各风格国风,欧美,悠闲 Q 版和写实角色原画,半身像,ui,图标,logo 设计等。请联系 Vx:xwblll

LeetCode 等刷题网站的出现是促进了内卷还是……?

Posted: 19 Aug 2021 11:59 PM PDT

安卓遇到未捕获的 Java 异常会直接崩溃,为什么要这么设计

Posted: 19 Aug 2021 11:46 PM PDT

既然代码都跑在消息循环里,为什么非 debug 版本的 app,系统不主动捕获异常,然后处理下一个消息?这样用户体验不是更好吗?

有没有快速给视频加硬字幕的方法

Posted: 19 Aug 2021 11:42 PM PDT

有时候给 mkv 文件加硬字幕用 handbrake 要好半天(不想用外挂字幕,设备问题),有无更快的方法

Vue 组件 props 改变时,如何阻止多余的 render

Posted: 19 Aug 2021 09:15 PM PDT

这是一个 Vue3 编写的异步加载的博文列表的组件,通过传入一个 postLang 来筛选不同语言的博文。

当 postLang 发生变化时,这个组件会被渲染两次,第一次时 postLang 发生变化时立即渲染,第二次是异步请求完成时刷新博文列表。

这个组件 render 时并没有直接引用 props 里的变量,所以第一次渲染时我的组件中没有任何需要更新的内容, 这次渲染显然是多余的,那么我们可以阻止它进行吗

Lang: Vue BlogPost: create BlogPost: render // 显示正在加载... BlogPost: render // 显示 Lang 为 Vue 的博文 Lang: Vuex        BlogPost: render // 无用的 render BlogPost: render // 显示 Lang 为 Vuex 的博文 
export const BlogPost = defineComponent({     name: 'BlogPost',     props: {         postLang: {             type: String,             default: 'Vue'         }     },     setup(props) {         console.log(BlogPost.name + ': create');          const {postLang} = toRefs(props);          const postList = ref<{ title: string }[]>([]);          onMounted(async () => postList.value = await fetchPostList(postLang.value));         watch(postLang, async () => postList.value = await fetchPostList(postLang.value));          return () => {             console.log(BlogPost.name + ': render');              const renderContent = () => {                 if (postList.value.length === 0) {                     return <div>正在加载中...</div>;                 } else {                     return postList.value.map(post => <BlogPostItem title={post.title}/>);                 }             };              return (                 <div>                     {renderContent()}                 </div>             );         };     } }); 

下面来看一个更加清晰的例子,这一次我们在 setup 函数中完全不用 props,显然组件的内部状态完全不受 props 干扰,但是当入参 props 改变时,我们查看日志可以发现,组件仍然会重新 render 。而如果把 props 换成是 Vue Ref (非组合式 API 的 data ),如果只要 render 函数中没有调用这个 ref,那么组件就不会因为 ref 的改变而被重新 render,那么对于 props,Vue 是否可以有同样的优化,来消除这些多余的 render 呢。

Lang: Vue BlogPostNotUseProps: create BlogPostNotUseProps: render // 显示正在加载... BlogPostNotUseProps: render // 显示 Lang 为 Vue 的博文(写死了) Lang: Vuex        BlogPostNotUseProps: render // 无用的 render 
export const BlogPostNotUseProps = defineComponent({     name: 'BlogPostNotUseProps',     props: {         postLang: {             type: String,             default: 'Vue'         }     },     setup(props) {         console.log(BlogPostNotUseProps.name + ': create');          // const {postLang} = toRefs(props);          const postList = ref<{ title: string }[]>([]);          onMounted(async () => postList.value = await fetchPostList('Vue'));         // watch(postLang, async () => postList.value = await fetchPostList(postLang.value));          return () => {             console.log(BlogPostNotUseProps.name + ': render');              const renderContent = () => {                 if (postList.value.length === 0) {                     return <div>正在加载中...</div>;                 } else {                     return postList.value.map(post => <BlogPostItem title={post.title}/>);                 }             };              return (                 <div>                     {renderContent()}                 </div>             );         };     } }); 

Windows 下用 mongodump 命令,很小的数据库也花 8 秒

Posted: 19 Aug 2021 08:55 PM PDT

感觉时间花在了连接认证那部分,但是数据库都在本地
mongodump -h localhost:27017 -d tst_00062 -o c:/t/dbbackup --gzip
⇒有什么忽略认证提速的方法吗?

我用 Pymongo 连接下载的话半秒左右。
⇒但是无法取得 meta 文件。Pymongo 有办法拿到数据库的 meta 信息吗?

Manager 类怎么怎么翻译成中文比较合适?

Posted: 19 Aug 2021 08:42 PM PDT

管理器类?管理者类?

用 Go 轻松完成一个 TCC 分布式事务,保姆级教程

Posted: 19 Aug 2021 07:33 PM PDT

什么是 TCC,TCC 是 Try 、Confirm 、Cancel 三个词语的缩写,最早是由 Pat Helland 于 2007 年发表的一篇名为《 Life beyond Distributed Transactions:an Apostate's Opinion 》的论文提出。

TCC 组成

TCC 分为 3 个阶段

  • Try 阶段:尝试执行,完成所有业务检查(一致性), 预留必须业务资源(准隔离性)
  • Confirm 阶段:如果所有分支的 Try 都成功了,则走到 Confirm 阶段。Confirm 真正执行业务,不作任何业务检查,只使用 Try 阶段预留的业务资源
  • Cancel 阶段:如果所有分支的 Try 有一个失败了,则走到 Cancel 阶段。Cancel 释放 Try 阶段预留的业务资源。

TCC 分布式事务里,有 3 个角色,与经典的 XA 分布式事务一样:

  • AP/应用程序,发起全局事务,定义全局事务包含哪些事务分支
  • RM/资源管理器,负责分支事务各项资源的管理
  • TM/事务管理器,负责协调全局事务的正确执行,包括 Confirm,Cancel 的执行,并处理网络异常

如果我们要进行一个类似于银行跨行转账的业务,转出( TransOut )和转入( TransIn )分别在不同的微服务里,一个成功完成的 TCC 事务典型的时序图如下: image.png

TCC 网络异常

TCC 在整个全局事务的过程中,可能发生各类网络异常情况,典型的是空回滚、幂等、悬挂,由于 TCC 的异常情况,和 SAGA 、可靠消息等事务模式有相近的地方,因此我们把所有异常的解决方案统统放在这篇文章《还被分布式事务的网络异常困扰吗?一个函数调用帮你搞定它》进行讲解

TCC 实践

对于前面的跨行转账操作,最简单的做法是,在 Try 阶段调整余额,在 Cancel 阶段反向调整余额,Confirm 阶段则空操作。这么做带来的问题是,如果 A 扣款成功,金额转入 B 失败,最后回滚,把 A 的余额调整为初始值。在这个过程中如果 A 发现自己的余额被扣减了,但是收款方 B 迟迟没有收到余额,那么会对 A 造成困扰。

更好的做法是,Try 阶段冻结 A 转账的金额,Confirm 进行实际的扣款,Cancel 进行资金解冻,这样用户在任何一个阶段,看到的数据都是清晰明了的。

下面我们进行一个 TCC 事务的具体开发

目前可用于 TCC 的开源框架,主要为 Java 语言,其中以 seata 为代表。我们的例子采用 go 语言,使用的分布式事务框架为https://github.com/yedf/dtm,它对分布式事务的支持非常优雅。下面来详细讲解 TCC 的组成

我们首先创建两张表,一张是用户余额表,一张是冻结资金表,建表语句如下:

CREATE TABLE dtm_busi.`user_account` (   `id` int(11) AUTO_INCREMENT PRIMARY KEY,   `user_id` int(11) not NULL UNIQUE ,   `balance` decimal(10,2) NOT NULL DEFAULT '0.00',   `create_time` datetime DEFAULT now(),   `update_time` datetime DEFAULT now() );  CREATE TABLE dtm_busi.`user_account_trading` (   `id` int(11) AUTO_INCREMENT PRIMARY KEY,   `user_id` int(11) not NULL UNIQUE ,   `trading_balance` decimal(10,2) NOT NULL DEFAULT '0.00',   `create_time` datetime DEFAULT now(),   `update_time` datetime DEFAULT now() ); 

trading 表中,trading_balance 记录正在交易的金额。

我们先编写核心代码,冻结 /解冻资金操作,会检查约束 balance+trading_balance >= 0,如果约束不成立,执行失败

func adjustTrading(uid int, amount int) (interface{}, error) {   幂等、悬挂处理   dbr := sdb.Exec("update dtm_busi.user_account_trading t join dtm_busi.user_account a on t.user_id=a.user_id and t.user_id=? set t.trading_balance=t.trading_balance + ? where a.balance + t.trading_balance + ? >= 0", uid, amount, amount)   if dbr.Error == nil && dbr.RowsAffected == 0 { // 如果余额不足,返回错误     return nil, fmt.Errorf("update error, balance not enough")   }   其他情况检查及处理 } 

然后是调整余额

func adjustBalance(uid int, amount int) (ret interface{}, rerr error) {   幂等、悬挂处理   这里略去进行相关的事务处理,包括开启事务,以及在 defer 中处理提交或回滚   // 将原先冻结的资金记录解冻   dbr := db.Exec("update dtm_busi.user_account_trading t join dtm_busi.user_account a on t.user_id=a.user_id and t.user_id=? set t.trading_balance=t.trading_balance + ?", uid, -amount)   if dbr.Error == nil && dbr.RowsAffected == 1 { // 解冻成功     // 调整金额     dbr = db.Exec("update dtm_busi.user_account set balance=balance+? where user_id=?", amount, uid)   }   其他情况检查及处理 } 

下面我们来编写具体的 Try/Confirm/Cancel 的处理函数

RegisterPost(app, "/api/TransInTry", func (c *gin.Context) (interface{}, error) {   return adjustTrading(1, reqFrom(c).Amount) }) RegisterPost(app, "/api/TransInConfirm", func TransInConfirm(c *gin.Context) (interface{}, error) {   return adjustBalance(1, reqFrom(c).Amount) }) RegisterPost(app, "/api/TransInCancel", func TransInCancel(c *gin.Context) (interface{}, error) {   return adjustTrading(1, -reqFrom(c).Amount) })  RegisterPost(app, "/api/TransOutTry", func TransOutTry(c *gin.Context) (interface{}, error) {   return adjustTrading(2, -reqFrom(c).Amount) }) RegisterPost(app, "/api/TransOutConfirm", func TransInConfirm(c *gin.Context) (interface{}, error) {   return adjustBalance(2, -reqFrom(c).Amount) }) RegisterPost(app, "/api/TransOutCancel", func TransInCancel(c *gin.Context) (interface{}, error) {   return adjustTrading(2, reqFrom(c).Amount) })  

到此各个子事务的处理函数已经 OK 了,然后是开启 TCC 事务,进行分支调用

// TccGlobalTransaction 会开启一个全局事务 _, err := dtmcli.TccGlobalTransaction(DtmServer, func(tcc *dtmcli.Tcc) (rerr error) {   // CallBranch 会将事务分支的 Confirm/Cancel 注册到全局事务上,然后直接调用 Try   res1, rerr := tcc.CallBranch(&TransReq{Amount: 30}, host+"/api/TransOutTry", host+"/api/TransOutConfirm", host+"/api/TransOutRevert"   进行错误检查,以及其他逻辑   res2, rerr := tcc.CallBranch(&TransReq{Amount: 30}, host+"/api/TransInTry", host+"/api/TransInConfirm", host+"/api/TransInRevert")   进行错误检查,有任何错误,返回错误,回滚交易   // 如果没有错误,函数正常返回后,全局事务会提交,TM 会调用各个事务分支的 Confirm,完成整个事务 }) 

至此,一个完整的 TCC 分布式事务编写完成。

如果您想要完整运行一个成功的示例,那么按照 dtm 项目的说明搭建好环境之后,运行下面命令运行 tcc 的例子即可

go run app/main.go tcc_barrier

TCC 的回滚

假如银行将金额准备转入用户 2 时,发现用户 2 的账户异常,返回失败,会怎么样?我们修改代码,模拟这种情况:

RegisterPost(app, "/api/TransInTry", func (c *gin.Context) (interface{}, error) {   return gin.H{"dtm_result":"FAILURE"}, nil }) 

这是事务失败交互的时序图 image.png

这个跟成功的 TCC 差别就在于,当某个子事务返回失败后,后续就回滚全局事务,调用各个子事务的 Cancel 操作,保证全局事务全部回滚。

小结

在这篇文章里,我们介绍了 TCC 的理论知识,也通过一个例子,完整给出了编写一个 TCC 事务的过程,涵盖了正常成功完成,以及成功回滚的情况。相信读者通过这边文章,对 TCC 已经有了深入的理解。

关于分布式事务中需要处理的幂等、悬挂、空补偿,请参考另一篇文章:分布式事务你不能不知的坑,一个函数调用帮你搞定它

关于分布式事务更多更全面的知识,请参考分布式事务最经典的七种解决方案

文中使用的例子节选自yedf/dtm,支持多种事务模式:TCC 、SAGA 、XA 、事务消息 跨语言支持,已支持 golang 、python 、PHP 、nodejs 等语言的客户端。提供子事务屏障功能,优雅解决幂等、悬挂、空补偿等问题。 ​ 阅读完此篇干货,欢迎大家访问https://github.com/yedf/dtm项目,给颗星星支持!

git 合并分支问题

Posted: 19 Aug 2021 07:25 PM PDT

我创建了两个不同的存储库。 现在,我想将这些不同的存储库合并为一个主存储库,但作为主存储库中的分支。应该怎么做呢 ?

关于 safari 的一个小疑问

Posted: 19 Aug 2021 06:30 PM PDT

在开发的网页的时候遇到个问题想请教下大佬们!

场景:在 safari 中使用 svg,并且基于 input 框中输入的值通过操作 dom 同步更新 svg 里面 text 标签的内容

问题:在输入框输入的时候发现 dom 上的文案已经更新了,但是视图没有任何变化!(在谷歌上是正常更新)

暂时解决方案:手动给 svg 里面的每个 text 标签加上了一个 key,可以解决上述问题,但是不知道具体发生的原因,是 safari 的 bug 吗?

有什么是给程序员看的用来调查电脑卡顿的文章?

Posted: 19 Aug 2021 11:55 AM PDT

最近我的 win10 真是卡的难受,chrome 新建个标签页都卡,而且根本不是掉帧,连鼠标都明显卡一下。打开个网页时也会卡顿,滚动网页也卡。倒是看视频时不会卡,看起来解码视频的程序没什么问题。

cpu2700x,内存 24g,根本没开几个程序。

有什么文章是介绍怎么调查这种卡顿的,介绍一点适合程序员用专业一点的手段,让我调查一下,不行就只能重装了。

如何,定时增量同步 aws 实例上文件到 s3

Posted: 19 Aug 2021 10:46 AM PDT

规则如下

本地文件删除 s3 也删除 本地文件修改 s3 覆盖掉旧的 本地文件新增 s3 新增  

每几分钟一次即可

gocv 这个库用法,求哥哥们指点

Posted: 19 Aug 2021 10:24 AM PDT

找了个 C 代码是这样写的,问题是这个库在 cv::compare的时候没有 这个 cv::GC_PR_FGD 我在库里面 cgo 调用时把它改为了 3 也是不行的。

有兄弟知道 gocv 怎么调用 grabCut 来抠图吗


cv::Mat image= cv::imread("../tower.jpg"); if (!image.data)     {     cout<<"不能打开图像!"<<endl;     return 0;      }   cv::Rect rectangle(50,70,image.cols-150,image.rows-180);  cv::Mat result; cv::Mat bgModel,fgModel;  double tt = cv::getTickCount(); cv::grabCut(image,     result,     rectangle,     bgModel,fgModel,      cv::GC_INIT_WITH_RECT); // 用矩形 tt = cv::getTickCount() - tt; printf("算法执行执行时间:%g ms\n", tt/cv::getTickFrequency()*1000);  cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);  cv::Mat foreground(image.size(),CV_8UC3,cv::Scalar(255,255,255)); image.copyTo(foreground,result);  

求教一个专题的搜索引擎怎么搭建?

Posted: 19 Aug 2021 08:20 AM PDT

想着做一个特定方向的搜索引擎,比如只是搜索几个站点的搜索引擎,这样需要怎么样建设呢?

unraid 怎么设置 登录失败几次之后自动封禁 ip 找了半天没找到方法

Posted: 19 Aug 2021 08:03 AM PDT

因为准备端口转发到外网使用 但是直接转发 感觉不太安全的样子

请教:单元测试运行找不到类问题

Posted: 19 Aug 2021 07:51 AM PDT

代码目录结构是这样的:

├─src │  ├─main │  │  └─java │  │      └─com │  │          └─xx  Sample.java │  └─test │      └─java │          └─com │              └─xx SampleTest.java  

设置 src/main/java 目录为 Source root, src/test/java 为 test source root SampleTest.java 测试类中有调用 Sample 类中的方法 当我运行 SampleTest 单元测试方法时,提示找不到 com.xx.Sample.java 请问 这是为什么呢?依赖项目其他模块代码也是找不到类 在 IDEA 中,不会提示编译错误,只有运行时,在 testCompile 阶段提示找不到类,在跳过测试构建是正常的 运行测试使用的本地 maven 仓库已经指向了我使用的本地仓库(从 debug 日志中看到)

请大家帮帮我 谢谢大家了

No comments:

Post a Comment