DevilKing's blog

冷灯看剑,剑上几分功名?炉香无需计苍生,纵一穿烟逝,万丈云埋,孤阳还照古陵

0%

原文链接

Virtual Memory Size(VSZ) is all memory that the process can access, including memory that is swapped out, memory that is allocated, but not used, and memory that is from shared libraries. (Edited, good explanation in stackoverflow.)

Resident Set Size(RSS) is number of memory pages the process has in real memory multiplied by pagesize. This excludes swapped out memory pages.

一则

Go 通过 汇编或者 cgo 来调用这些系统调用,而不是 libc,所以它不提供 malloc, 而是直接向 OS 通过 mmap 要内存。Go 使用类似 TCMalloc: Thread-Caching Malloc 的方法管理内存。它比 libc malloc 更快效率更高,做法是使用 thread-local cache 存储预分配的内存对象。具体来说,给对象做大小分级,每个级别的管理都不太一样

golang内存模型

内存模型的目的是为了定义清楚变量的读写在不同执行体里的可见性。理解内存模型在并发编程中非常重要,因为代码的执行顺序和书写的逻辑顺序并不会完全一致,甚至在编译期间编译器也有可能重排代码以最优化CPU执行, 另外还因为有CPU缓存的存在,内存的数据不一定会及时更新,这样对内存中的同一个变量读和写也不一定和期望一样。

Go的并发模型是基于CSP(Communicating Sequential Process)的,不同的Goroutine通过一种叫Channel的数据结构来通信;Java的并发模型则基于多线程和共享内存,有较多的概念(violatie, lock, final, construct, thread, atomic等)和场景,当然java.util.concurrent并发工具包大大简化了Java并发编程

Happens-before 定义

Happens-before用来指明Go程序里的内存操作的局部顺序。如果一个内存操作事件e1 happens-before e2,则e2 happens-after e1也成立;如果e1不是happens-before e2,也不是happens-after e2,则e1和e2是并发的。

垃圾回收的时机

垃圾回收的触发是由一个gcpercent的变量控制的,当新分配的内存占已在使用中的内存的比例超过gcprecent时就会触发。比如,gcpercent=100,当前使用了4M的内存,那么当内存分配到达8M时就会再次gc。如果回收完毕后,内存的使用量为5M,那么下次回收的时机则是内存分配达到10M的时候。也就是说,并不是内存分配越多,垃圾回收频率越高,这个算法使得垃圾回收的频率比较稳定,适合应用的场景。

gcpercent的值是通过环境变量GOGC获取的,如果不设置这个环境变量,默认值是100。如果将它设置成off,则是关闭垃圾回收。

原文链接

repo

  • 300线程,循环1000次,共30w请求

秒杀后端只能部署有一个节点,因为商品的库存数据都在内存,而这些数据是不跨JVM共享的,放在内存中?

下单流程

通过JMS的消息,作为中间件来

Disruptor是LMAX公司开源的高性能内存队列。Disruptor能够让开发人员只需写单线程代码,就能够获得非常强悍的性能表现,同时避免了写并发编程的难度和坑。 其本质思想在于多线程未必比单线程跑的快。

backend利用它把从ActiveMQ Artemis获得请求串行化,判断商品库存是否充足,更新剩余库存,最后异步写入数据库。

库存充足判断、更新剩余库存的动作都是在内存中进行的,配合Disruptor绕过了并发编程的内存可见性、同步、锁等问题,性能非常强。

在本项目中商品在内存中相关类是Item.java,在利用jol-cli(点此下载)查看其memory-layout后发现,其大小为24byte:

http://central.maven.org/maven2/org/openjdk/jol/jol-cli/0.8/jol-cli-0.8-full.jar

me.chanjar.jms.server.memdb.Item object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 12 (object header) N/A 12 4 int Item.amount N/A 16 4 Long Item.id N/A 20 4 (loss due to the next object alignment) Instance size: 24 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

而Long占用的内存也为24b:

java.lang.Long object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 12 (object header) N/A 12 4 (alignment/padding gap) N/A 16 8 long Long.value N/A Instance size: 24 bytes Space losses: 4 bytes internal + 0 bytes external = 4 bytes total

假设你有100W商品需要秒杀,那么其占用内存 = 1,000,000 * (24b + 4b + 24b) = 52,000,000b = 49m。仅仅只占49m。

架构上的优化点

  1. 下单请求异步处理,请求返回的本次请求的ID,客户端拿这个ID到另行发起请求查询结果
  2. 在秒杀期间,商品库存信息在内存中,库存判断及库存扣减都在内存中进行,之后异步到数据库
  3. 利用Disruptor将并发请求串行化,同时避免了多线程编程复杂度
  4. 抛弃数据库事务,采用最终一致性

和JMS相关的优化点

  1. 重用JMS Connection、Session、MessageProducer、MessageConsumer,而不是每次都创建这些对象(Spring的JmsTemplate就是这么干的)
  2. 将JMS Session设定为transacted=false, AUTO_ACKNOWLEDGE
  3. 发送JMS消息时DeliveryMode=NON_PERSISTENT
  4. 关闭Artemis的重发、消息持久机制

下单请求的异步处理,将下单流程同单子的查询分为两个不同流程,这样进行异步操作

同时引入Disruptor,进行相关的串行化的工作

原文链接

性,用公式来表示,就是△Φ/Φ=C,其中Φ为原刺激量,△Φ为此时的差别阈限,C为常数,又称为韦柏率

我们的感觉很敏感,但也有惰性:它会蒙骗我们的眼睛,也会加重我们的感受而迷失理性。所以我们应带着谦卑的心对待万物众生,韦伯定律中的生活智慧是:给予方要多做雪中送炭的事,少做锦上添花的事,尽量不做画蛇添足的事;而受予方要懂得珍惜自己的点滴所得,善待身边的人

佛学的禅宗,跟所谓的心学部分?

心是菩提树,身为明镜台。明镜本清净,何处染尘埃。

身是菩提树,心如明镜台。时时勤拂拭,莫使有尘埃。


本周:

  • 开始刷leetcode部分的题目
  • 开始总结相关基础部分的知识
  • 运营广告平台相关内容

下周:

  • 整理以及修改简历,配合猎头,进行相关的投递
  • 继续刷题,巩固基础
  • sdk部分的一些策略梳理和整理

大考部分,算是见了面,不过心理还是挺抗拒的。。。不管是有没有做好准备,还是本身依然在自我怀疑状态。。。被赶鸭子上架了,只能是慢慢去拖一拖,磨一磨了。。

徐建的事情,算是有一个初步的结果,虽然整体结果不如意,但起码人还在,还有希望在。。。

感觉最近心不静,不管是之前制定的leetcode刷题计划,还是健身计划,还是面试的一些总结计划什么的,都没有好好地坚持下去。。。

尽量心静吧,保持学习的心态。。。

佛在彼岸,也在心中。。。修行。。。