天道酬勤

天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。

0%

 在做系统稳定性-下游用户接口的降级时,当时有2种方案,第一种是只校验用户uid(18位数字 long类型 8字节)是否非法,这种方案实现简单,但有一些缺陷;另一种方案是缓存一份用户信息(uid、城市、运营单元、收货地址id、手机号、身份 等) 数据,用户接口异常时用缓存数据校验,这种方案实现稍微复杂点,但是没有缺陷。

 当时有2亿多用户,别的组的同学缓存过全量(20多个字段)用户数据,用了200G内存。 由于占用内存太多,收益不高,他们很快就放弃缓存用户数据了。

 由于我们并不需要缓存用户的20多个字段,只需要缓存6个字段,想自己计算一下+实验下看需要多大内存,如果占用内存少可以使用方案二。

(1) redis整体存储结构

 redis整体数据存储结构

阅读全文 »

 在平时学习过很多Redis的知识点,解决过很多问题,但是感觉整体比较零散。为了比较系统、完整的了解Redis,总结出一篇博客,方便自己和大家了解。

 在看内容之前,先问大家一个问题,在使用redis get命令和set命令时,大家知道Redis是怎么执行的,涉及到哪些模块吗?

(1) Redis架构

 Redis架构

Redis系统架构主要包含 事件处理、数据管理、功能扩展、系统扩展等内容。

阅读全文 »

  相比于 Go 语言宣扬的“用通讯的方式共享数据”,通过共享数据的方式来传递信息和协调线程运行的做法其实更加主流,毕竟大多数的现代编程语言,都是用后一种方式作为并发编程的解决方案的。
  我们来了解一下go中的互斥锁sync.Mutex

(1) sync.Mutex是什么

  sync.Mutex是go语言里的一种互斥锁,是保证同步的一种工具。
  类似生活中去医院看病时挂号等医生叫号的过程,有很多患者挂号(协程),只有一个医生(资源),被叫号的患者(拿到锁)可以到诊室里让医生看病。看完病离开诊室(释放锁)。


(2) 为什么要用sync.Mutex

先看一个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package main

import "sync"

var sum int = 0
var wg sync.WaitGroup
var mu sync.Mutex

// 开10个协程并发执行1000次 sum++
// 如果不加 mu.lock() mu.unlock() 最后的结果不是10000 一般会小于10000
// 把 // mu.lock() // mu.unlock() 前面的注释删除,结果就是10000
// 这个是缓存导致的可见性问题。
// 具体原因是因为sum++不是原子操作,CPU分2条指令执行,CPU执行第2条指令时获取到的缓存sum值和主内存sum值不一致导致
func main() {

// fatal error: sync: unlock of unlocked mutex
// // mu.Unlock()

// 开10个协程并发执行1000次 sum=sum+1
for i := 0; i < 10; i++ {
wg.Add(1)
go funcAdd()
}
// 等所有协程执行完
wg.Wait()
println("result:", sum)

}

func funcAdd() {
for i := 0; i < 1000; i++ {
// 对sum加锁
//mu.Lock()
sum++
// 对sum解锁
//mu.Unlock()
//println("result=", sum)
}
// 没有下面这一行代码 提示 fatal error: all goroutines are asleep - deadlock!
wg.Done()
}

上面的代码主要功能是开10个协程并发执行1000次 sum++,并打印结果,可以自己执行一下,会发现执行的结果<10000。
把第33行 36行前的注释删掉,程序执行的结果就是结果就是10000

阅读全文 »

对于传统的电商,为了保障大促时系统稳定性,保证用户可以查看购买下单,有一个黄金流程,一般的黄金流程都包括4大领域
导购(首页、分类、商详、搜索)、营销(促销、权益、券)、交易(购物车、提单、下单、支付)、履约(接单、生产、配送)

阅读全文 »

(1) 什么是ReentrantLock

ReentrantLock是Java里的一种可重入锁。 也可以用来达到互斥的效果。
根据创建时的传参,可以分为公平锁和非公平锁。

阅读全文 »

synchronized是Java语言里互斥锁的一种实现。解决了原子性、可见性的问题。

synchronized 是基于底层操作系统的 Mutex Lock 实现的,每次获取和释放锁操作都会带来用户态和内核态的切换,从而增加系统性能开销。因此,在锁竞争激烈的情况下,synchronized 同步锁在性能上就表现得非常糟糕,它也常被大家称为重量级锁。

synchronized用法

synchronized 实现同步锁的方式有两种,一种是修饰方法,一种是修饰方法块。以下就是通过 Synchronized 实现的两种同步方法加锁的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class SynchronizedTest {

public static void main(String[] args){

}

/**
* 同步实例方法,锁实例对象
*/
public synchronized void test() {
}

/**
* 同步类方法,锁类对象
*/
public synchronized static void test1() {
}

/**
* 同步代码块
*/
public void test2() {
// 锁类对象
synchronized (SynchronizedTest.class) {
// 锁实例对象
synchronized (this) {

}
}
}

}
1
2
3
javac  SynchronizedTest.java  //先运行编译class文件命令

javap -v SynchronizedTest.class //再通过javap打印出字节文件
阅读全文 »

JVM调优前一定要只要遇到什么问题、优化后的目标。否则投入多收获少。得不偿失。

1
2
3
4
2020-11-17T04:59:16.623+0800: 5.285: [GC (Allocation Failure) 2020-11-17T04:59:16.624+0800: 5.285: [ParNew2020-11-17T04:59:16.648+0800: 5.309: [SoftReference, 0 refs, 0.0002508 secs]2020-11-17T04:59:16.648+0800: 5.309: [WeakReference, 332 refs, 0.0001633 secs]2020-11-17T04:59:16.648+0800: 5.310: [FinalReference, 5452 refs, 0.0057402 secs]2020-11-17T04:59:16.654+0800: 5.315: [PhantomReference, 0 refs, 0 refs, 0.0002858 secs]2020-11-17T04:59:16.654+0800: 5.316: [JNI Weak Reference, 0.0000681 secs]
Desired survivor size 107347968 bytes, new threshold 6 (max 6)
- age 1: 17515352 bytes, 17515352 total
: 1677824K->17187K(1887488K), 0.0309183 secs] 1677824K->17187K(6081792K), 0.0310078 secs] [Times: user=0.14 sys=0.02, real=0.03 secs]
1
2
3
4
5
6
2020-11-17T04:59:17.966+0800: 6.628: [CMS-concurrent-abortable-preclean: 1.144/1.845 secs] [Times: user=4.88 sys=0.32, real=1.84 secs]
2020-11-17T04:59:17.966+0800: 6.628: [GC (CMS Final Remark) [YG occupancy: 925231 K (1887488 K)]2020-11-17T04:59:17.967+0800: 6.628: [Rescan (parallel) , 0.0808829 secs]2020-11-17T04:59:18.047+0800: 6.709: [weak refs processing2020-11-17T04:59:18.047+0800: 6.709: [SoftReference, 0 refs, 0.0002601 secs]2020-11-17T04:59:18.048+0800: 6.709: [WeakReference, 0 refs, 0.0001719 secs]2020-11-17T04:59:18.048+0800: 6.709: [FinalReference, 0 refs, 0.0001500 secs]2020-11-17T04:59:18.048+0800: 6.709: [PhantomReference, 0 refs, 0 refs, 0.0002673 secs]2020-11-17T04:59:18.048+0800: 6.710: [JNI Weak Reference, 0.0000138 secs], 0.0009146 secs]2020-11-17T04:59:18.048+0800: 6.710: [class unloading, 0.0111246 secs]2020-11-17T04:59:18.059+0800: 6.721: [scrub symbol table, 0.0063213 secs]2020-11-17T04:59:18.066+0800: 6.727: [scrub string table, 0.0006271 secs][1 CMS-remark: 0K(4194304K)] 925231K(6081792K), 0.1009594 secs] [Times: user=0.33 sys=0.01, real=0.10 secs]
2020-11-17T04:59:18.068+0800: 6.729: [CMS-concurrent-sweep-start]
2020-11-17T04:59:18.068+0800: 6.729: [CMS-concurrent-sweep: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
2020-11-17T04:59:18.068+0800: 6.729: [CMS-concurrent-reset-start]
2020-11-17T04:59:18.165+0800: 6.827: [CMS-concurrent-reset: 0.098/0.098 secs] [Times: user=0.11 sys=0.08, real=0.10 secs]

GC (Allocation Failure)
Concurrent Abortable Preclean
CMS-concurrent-abortable-preclean

References

[]
[]
[] JVM调优实战:解决CMS concurrent-abortable-preclean LongGC的问题