V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  fkdtz  ›  全部回复第 1 页 / 共 35 页
回复总数  693
1  2  3  4  5  6  7  8  9  10 ... 35  
18 小时 15 分钟前
回复了 lsk569937453 创建的主题 程序员 目前来看 CAP 理论中的 CP 和 AP 最容易造的轮子是?
Redis 不是 AP 的么
1 天前
回复了 SlowDown 创建的主题 程序员 锁续期和锁归属问题?
都永久有效的锁了,还怎么自动释放?
你要不再好好看看
1 天前
回复了 SlowDown 创建的主题 程序员 锁续期和锁归属问题?
@SlowDown
这里强调的是锁带上有效期的必要性,即如果用一个永久有效的锁并且不使用续期线程会有什么问题。
另外我没看懂你的疑问是什么?
2 天前
回复了 SlowDown 创建的主题 程序员 锁续期和锁归属问题?
虽然有守护线程持续的续约锁,但还是有必要在释放锁时做校验的,关键在于「你不能假设系统任何时刻都能正常运行」
假如锁续期的守护进程出现异常而没有正常执行续期,那么直接释放锁而不做校验就会出现锁被误删除的情况。

其实你有没有想过,既然锁续期线程一直在给锁延长有效期,那不就相当于是一把永久有效的锁吗?那直接用一个不加有效期的永久锁不就好了,为什么还要弄个有效期再加一个续期线程?而且如果用一个永久有效的锁甚至连锁误删除的问题也不会存在了。

选择用带有效期的锁的原因跟前面的问题有同样的考虑:「你不能假设系统任何时刻都能正常运行」,如果主线程加锁后挂掉,那么不加有效期的锁就会一直存在,所以必须要带上有效期,带上有效期就引出了锁归属和锁续期的概念,进而才引出后面的各种方案。
5 天前
回复了 main1234 创建的主题 程序员 golang 关于 forrange 的一些疑问
我认为综合 4 、5 、6 楼的回复已经可以完整回答的楼主的问题了,不过貌似楼主有一点模糊,我根据自己的理解再具象化地补充一下,或许可以帮助楼主理解,也希望能和大家一起交流学习。
搞清楚下面 3 个 go 的特性可能有助于理解上面的代码发生了什么:
1.go 的自动引用和自动解引用; 2.defer 的求值时机和执行时机 3.for 循环变量只初始化一次之后一直在复用(go1.22 以前)

第一个特性自动引用和解引用指的是,如果一个方法是定义在指针类型上的,那么你可以通过该类型的值对象来调用方法。例如代码中 func (u *Users) GetName()定义在 *User 上,但却可以在 for 循环 users1[]Users 时通过 u.GetName() 调用。这里的完整写法其实应该是 (&u).GetName()。
自动解引用就是反过来,方法定义在值类型上,但允许你在指针类型上直接调用。

第二个特性 defer 的执行时机大家都懂,只是需要明确的是 defer 后面语句的求值时机,是在执行到这一行时就要求值,之后压栈。

第三个特性是循环变量 u 只初始化一次,即 u 的地址不会变(go1.22 之前),后面的循环是将新的列表元素值赋值给 u 。

现在回头看为什么第一个 for 打出 ccc ?
我们排除掉自动引用的干扰,还原完整写法,users1 的 for 循环中完整写法应该是 defer (&u).GetName(),执行到这里就得求值并压栈,压入的是 u 的地址,之后进入后面循环。
由于 u 只初始化一次,所以之后的循环中 u 的地址一直不变,只是在更新他的值,所以再次执行 defer (&u).GetName() 时压入的也还是 u 的地址,就这样一共循环 3 次,压了 3 次 u 的地址,最后 u 装的是 Users("c"),所以 GetName()打出三次 c 。

再看为什么第二个 for 打出 zyx ?
理解了第一个 for 也就能理解第二个 for 了,这次执行 defer u.GetName() 时不需要自动引用,因为 u 本身就是*User 类型,那么此时求值压栈,压入的就是 u 的值,注意 u 是指针,虽然 u 只初始化一次 u 的地址不变,但我们压入的并不是 u 的地址,而是 u 的值,u 的值是*User("x"),也就是 User("x")的地址,接着第二次循环,压入 User("y")地址,最后压入 User("z")地址,最终执行,得到结果就是 zyx 。

换一个角度思考,可以将 GetName 定义到 User 上,即 func (u Users) GetName(),其余代码不需要做改动,可以输出 zyxcba ,相当于 user1 循环不涉及自动引用,而 users2 循环中会自动解引用。

我想这也是很多 for 循环中如果嵌套函数或 goroutine 时,比较推荐用函数参数传值的方式而不是闭包的原因,因为 go 全都是值传递,这样就省掉了很多变量在函数内外生命周期的问题,心智负担轻了很多。

最后 4 楼提到在 go 1.22 版本做了修改,for 循环时循环变量已经改成每次循环都是一个全新变量了,这一点可以观察 u 的地址就能看到新版本确实每次循环都在发生变化,这样一来也就不存在上述问题了。
有过类似经历,我当时情况是被种了挖矿脚本导致 CPU 跑满。
解决办法是 top 找到异常进程干掉,找到异常 cron 清理掉,再把没有认证的端口都封掉。
5 天前
回复了 cuishuang 创建的主题 Redis Redis 加上密码后,整体性能下降 20%?
无论从实际使用经验,还是 Redis 的设计原则、还是 client server 通信原理来看,好像都不大可能啊。
他没说具体什么原因导致的吗?
极客时间上的课不都是付费的么,应该很严谨才对,评论中没有提出疑问的么。
个人有一个观点是不要过度设计,架构是演进出来的不是设计出来的。做一些可预见的设计优化是对的,但不要想的太多做的太早,否则你会发现要么设计的东西根本用不到、要么就是不符合业务发展需要不断重构。

回到问题,我认为封装的根本是分层思想。最基本的封装就是调用一个函数了,稍微进一步调用另一个文件中的函数,再如调用另一个包中的函数,再如调用另一个服务给你提供的函数,这些我认为都是分层,函数调用可以认为是陷入另一个层再回来,操作系统调用就是 trap 到内核层再回到用户层。
分层可以让你专注你自己的业务,其他的东西由别的层负责,例如限流、风控、鉴权、日志等都是与具体业务无关的通用的功能,就可以考虑封装为独立的一层。

到了具体实现环节我认为应该首先确定好接口,接口意味着协议,至少应该是一个在未来可以扩展的协议,这对分层来说是十分重要的,也意味着未来的修改没有历史包袱。另外应该尽量做到对业务无侵入性或尽量小,否则如果与业务有很强的耦合性就应该再思考一下是不是哪里不合理了。
作为一名 2012 年注册的博客园用户和开发者,真心祝愿博客园能干成。

博客园众包平台项目的定位是「软件**任务**众包平台」,这个定位切入点非常精准,我认为是有机会做成的,但同时也面临不少风险挑战。

机会:
- 博客园把软件开发拆分成一个个任务分配到平台开发者,这一点是最大的创新,相当于把非标准化的定制需求打散成了一个个标准化的任务,这样就可以释放出巨大的供给,可以把那些没有大块时间做开发的人力吸收进来,说具体一点也许未来开发者下了班回到家花一个小时就可以完成一个任务,赚个零花钱。
- 未来一定是服务业高度发展的社会,其中包括生产性服务业和生活性服务业,而软件定制开发就属于生产性服务业。服务业规模的扩大引发服务个性化消费需求需要有定制的服务来满足。

风险和挑战:
- 需求端的不确定性:在博客园原文中描述了需求端,需求端主要是有自己开发团队的 IT 企业,众包平台不涉及软件开发项目中的需求管理、项目管理、UI 设计而只涉及写代码,这个模式很像消费行业的 OEM 模式,企业定制需求然后交给工厂生产。这种模式对软件企业来说还是一个比较新的模式,可能需要一段时间的市场探索,说白了也是成本问题,如果哪一天外包成本低于自有团队成本,这个事儿也就成了,但过程中肯定需要很长一段路要走。
- 对需求端企业的要求极高:需求端企业要有超强的项目分析拆解能力和项目管理能力,才能将需求拆分成可以独立完成的子任务以及各个子任务之间的联调最终完成整个项目。相当于企业舍弃掉了开发能力,但要大幅提高项目管理能力,有点分布式 CAP 的意思。这对企业来说恐怕很难做到。
- 项目质量如何保证:假如视这个模式为 C2B 模式,那么既然是 C 端提供产出,那么由谁来保证 C 端产出的质量?如果还是交给企业自己解决,那么对企业来说成本太高了。
个人曾经在企业有过类似经历,需要引入小游戏场景,由于没有小游戏开发团队,所以找了外包驻场,整个项目并不顺利,几度延期后最终交付效果也不是很满意,最终还是选择了组建自有团队,可想而知外包和自有团队的成本差距了。

所以我看在这个项目中关键点在于需求端的市场培养和如何降低需求端的成本,具体来说如何让需求端企业更合理的拆解任务、更稳妥的推进项目、更轻松的验收结果是关键,平台的任务很艰巨。

最后还是想说,应该用发展的眼光看问题,虽然现阶段来看风险和挑战比机会要多,但未来谁也说不准,随着社会发展很多要素会发生变化,凭借博客园的用户口碑和团队对于产品路线的坚持,我希望博客园能够干成。
@Cy86 我图里才 1.6MB/s ,你跑 50MB/s 那相当于单机跑出几万 QPS 了
我也接到短信了,话术是有几十万积分月底清零,点链接兑换,还好我这个人比较穷,几十万积分怎么可能??
写了个脚本跑的热门电商搜索词,大部分请求都是返回空商品列表,估计商城里商品并不多,猜也就是几百个品差不多了。
https://i.imgur.com/hZxgDex.png
24 天前
回复了 lazyczx 创建的主题 MySQL 在看《高性能 MySQL》第 3 版,有点问题想问
MVCC = trx_id + roll_pointer + undolog 版本链 + ReadView
ReadView 结构中维护了当前事务开启时的活跃事务 id 列表,判断可见性就是 5 楼说的规则,这就保证了 repeatable read 隔离级别下不会出现不可重复读问题。

至于幻读问题,按照 SQL 标准来说 repeatable read 隔离级别是会出现的,但 MySQL InnoDB 的实现中避免了幻读,主要是通过 MVCC + Gap Locks 实现的。因为幻读描述的是在一个区间内的两次查询会出现原本不存在的行、或原本存在的行消失了,Gap Locks 通过在一个区间内加锁,导致后续事务无法修改数据,从而避免了幻读的发生。
你都说高峰期接口耗时日志明显增加,建议先查后端逻辑。
有可能后端因为某种原因响应很慢,导致 Nginx worker 无法快速响应前端,直到把 worker 全都占满。
如果是这种情况的话,问题出在后端,调高负载均衡配置不解决根本问题。
33 天前
回复了 wangpugod2003 创建的主题 程序员 讨论一道面试题啊(take home task)
@Sawyerhou topK 用小顶堆恰恰就是为了不把所有数据放进堆里吧,这样复杂度 logk ,要是用大顶堆 logn 了。
还是说我没理解你的意思,用大顶堆是有什么特殊考虑吗?
33 天前
回复了 wangpugod2003 创建的主题 程序员 讨论一道面试题啊(take home task)
这题如果是纯算法题,那么除了外部排序加最小堆真没别的思路了。
如果是个实际工程题那就可以并发处理,每组并发线程都做 topK ,最后汇总 topK ,类似 MapReduce 。

蹲个后续看看纯算法的话有其他什么方案。
37 天前
回复了 rockyliang 创建的主题 Go 编程语言 关于 golang 官网一段代码的疑惑
官网这篇文章确实有些晦涩,甚至文档一开始就表示如果想要搞协程,建议干脆直接用 channel 或 sync 包就完了,不用看文章内容。
可能官方文档出于严谨考虑,写的东西非常理论化,实际效果又有点反直觉,确实不好理解。
我读过几次心得主要是,文章说明了 go 在协程并发环境下可以提供的保证有哪些,也就是所谓 happens before 、synchronized before 这类保证,这种保证可以让开发者放心的写代码,因为只要符合这些保证生效的场景,就必然可以得到可预期的结果。
反之除了文章中提到的场景外,其他并发场景就不提供任何保证了,换句话说啥结果都可能冒出来。

至于为什么可能出现死循环,我想应该跟底层硬件有关了,例如 sync 包很多同步操作底层都涉及到屏障操作,就是让不同 CPU 寄存器中的数据可以在一致的前提下被读写,那么反之如果不使用任何同步原语,那也就不涉及到屏障操作,不同 CPU 可能持有的还是各自不同的副本...
1  2  3  4  5  6  7  8  9  10 ... 35  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1743 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 30ms · UTC 00:05 · PVG 08:05 · LAX 17:05 · JFK 20:05
Developed with CodeLauncher
♥ Do have faith in what you're doing.