西维蜀黍

【Golang】类型 - Channel

Channel

Channels are type safe message queues that have the intelligence to control the behavior of any goroutine attempting to receive or send on it. A channel acts as a conduit between two goroutines and will synchronize the exchange of any resource that is passed through it. It is the channel’s ability to control the goroutines interaction that creates the synchronization mechanism.

When a channel is created with no capacity, it is called an unbuffered channel. In turn, a channel created with capacity is called a buffered channel.

熟悉Golang的人都知道一句名言:“使用通信(channel)来共享内存,而不是通过共享内存来通信”。这句话有两层意思,Go语言确实在sync包中提供了传统的锁机制,但更推荐使用channel来解决并发问题。

它的操作符是箭头 <- 。

ch <- v    // 发送值v到Channel ch中
v := <-ch  // 从Channel ch中接收数据,并将数据赋值给v
  ...


【Golang】使用 - 限时调用一个函数(超时退出)

使用 time.After

package main

import (
   "fmt"
   "time"
)

func main() {

   c1 := make(chan string, 1)
   go func() {
      fmt.Printf("before sleep: %v\n", time.Now())
      time.Sleep(2 * time.Second)
      c1 <- "result 1"
      // Never go to here
      fmt.Printf("after sleep: %v\n", time.Now())
   }()

   fmt.Printf("before select: %v\n", time.Now())
   select {
   case res := <-c1:
      fmt.Println(res)
   case <-time.After(1 * time.Second):
      fmt.Println("timeout 1")
   }
   fmt.Printf("after select: %v\n", time.Now())
}

Output:

before select: 2020-11-24 22:57:40.129712 +0800 +08 m=+0.000122644
before sleep: 2020-11-24 22:57:40.129721 +0800 +08 m=+0.000131671
timeout 1
after select: 2020-11-24 22:57:41.13308 +0800 +08 m=+1.003459705
  ...


【Golang】map 并发问题

Problem

If you need to read from and write to a map from concurrently executing goroutines, the accesses must be mediated by some kind of synchronization mechanism. One common way to protect maps is with sync.RWMutex.

package main
func main() {
	m := make(map[int]int)
	go func() {
		for {
			_ = m[1]
		}
	}()
	go func() {
		for {
			m[2] = 2
		}
	}()
	select {}

}

错误信息是: fatal error: concurrent map read and map write。

  ...


【OpenWrt】WIFI 中继(relay)设置

This image shows an example setup. LAN interface of the Wi-Fi extender device MUST be on a different subnet for relayd to work (since it is routing traffic, it expects 2 different subnets).

Since both ethernet ports and Access Point Wi-Fi network are on the same LAN interface, all clients connecting to the Ethernet ports and to the Access Point Wi-Fi network of the Wi-Fi extender device will be routed by relayd and will be connected to your main network.

The LAN interface subnet will be used only as a “management” interface, as devices connecting to the Wi-Fi repeater will be on the main network’s subnet instead. You will have to set your PC with a static address in the same subnet as the LAN interface (like 192.168.2.10 for our example) to connect again to the Wi-Fi repeater’s Luci GUI or SSH.

  ...


【macOS】命令 - Launchctl

What is launchd?

Wikipedia defines launchd as “a unified, open-source service management framework for starting, stopping and managing daemons, applications, processes, and scripts. Written and designed by Dave Zarzycki at Apple, it was introduced with Mac OS X Tiger and is licensed under the Apache License.”

launchctl

launchctl 管理OS X的启动脚本,控制启动计算机时需要开启的服务。也可以设置定时执行特定任务的脚本,就像Linux crontab一样, 通过加装*.plist文件执行相应命令。

Job Definitions

The behavior of a daemon/agent is specified in a special XML file called a property list. Depending on where it is stored it will be treated as a daemon or an agent.

Job definitions crucial for the operation of the operating system are stored below /System/Library. You should never need to create a daemon or agent in these directories. Third-Party definitions which are relevant for every user are stored below /Library. Job definitions for a specific user are stored below the respective user’s Library directory.

Type Location Run on behalf of
User Agents ~/Library/LaunchAgents Currently logged in user
Global Agents /Library/LaunchAgents Currently logged in user
Global Daemons /Library/LaunchDaemons root or the user specified with the key UserName
System Agents /System/Library/LaunchAgents Currently logged in user
System Daemons /System/Library/LaunchDaemons root or the user specified with the key UserName

Daemons and Agents

launchd differentiates between agents and daemons. The main difference is that an agent is run on behalf of the logged in user while a daemon runs on behalf of the root user or any user you specify with the UserName key.

  ...


【Linux】OOM Killer

Out of memory (OOM)

Out of memory (OOM) is an often undesired state of computer operation where no additional memory can be allocated for use by programs or the operating system. Such a system will be unable to load any additional programs, and since many programs may load additional data into memory during execution, these will cease to function correctly. This usually occurs because all available memory, including disk swap space, has been allocated.

  ...


【Performance】Linux 性能问题调优 - 内存

Background

物理内存就是系统硬件提供的内存大小,是真正的内存,相对于物理内存,在linux下还有一个虚拟内存的概念,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(Swap Space)。

作为物理内存的扩展,linux会在物理内存不足时,使用交换分区的虚拟内存,更详细的说,就是内核会将暂时不用的内存块信息写到交换空间,这样以来,物理内存得到了释放,这块内存就可以用于其它目的,当需要用到原始的内容时,这些信息会被重新从交换空间读入物理内存。

linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。

在Linux内存管理中,主要是通过“调页Paging”和“交换Swapping”来完成上述的内存调度。调页算法是将内存中最近不常使用的页面换到磁盘上,把活动页面保留在内存中供进程使用。交换技术是将整个进程,而不是部分页面,全部交换到磁盘上。

分页(Page)写入磁盘的过程被称作Page-Out,分页(Page)从磁盘重新回到内存的过程被称作Page-In。当内核需要一个分页时,但发现此分页不在物理内存中(因为已经被Page-Out了),此时就发生了分页错误(Page Fault)。

  ...


【Performance】Linux 性能问题调优 - dmesg

Write the kernel messages to standard output.

Show kernel messages

$ dmesg

-L - 输出日志显示颜色

如果输出的日志是纯白或纯黑的,就会显得很不友善,想要colorful就可以加上-L选项:

$ dmesg -L
  ...


【Redis】分布式锁(Distributed Lock)

SETNX key value

Set key to hold string value if key does not exist. In that case, it is equal to SET. When key already holds a value, no operation is performed. SETNX is short for “SET if Not eXists”.

Return value

Integer reply, specifically:

  • 1 if the key was set
  • 0 if the key was not set

Examples

redis> SETNX mykey "Hello"
(integer) 1
redis> SETNX mykey "World"
(integer) 0
redis> GET mykey
"Hello"
redis> 
  ...


【Redis】诊断

大 key

$ redis-cli  --bigkeys
# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).

[00.00%] Biggest string found so far 'key316' with 3 bytes
[00.00%] Biggest string found so far 'key7806' with 4 bytes
[12.79%] Biggest zset   found so far 'salary' with 1 members
[13.19%] Biggest string found so far 'counter:__rand_int__' with 6 bytes
[13.50%] Biggest hash   found so far 'websit' with 2 fields
[14.37%] Biggest set    found so far 'bbs' with 3 members
[14.67%] Biggest hash   found so far 'website' with 3 fields
[30.41%] Biggest list   found so far 'mylist' with 100000 items
[95.53%] Biggest zset   found so far 'page_rank' with 3 members

-------- summary -------

Sampled 10019 keys in the keyspace!
Total key length in bytes is 68990 (avg len 6.89)

Biggest string found 'counter:__rand_int__' has 6 bytes
Biggest   list found 'mylist' has 100000 items
Biggest    set found 'bbs' has 3 members
Biggest   hash found 'website' has 3 fields
Biggest   zset found 'page_rank' has 3 members

10011 strings with 38919 bytes (99.92% of keys, avg size 3.89)
3 lists with 100003 items (00.03% of keys, avg size 33334.33)
1 sets with 3 members (00.01% of keys, avg size 3.00)
2 hashs with 5 fields (00.02% of keys, avg size 2.50)
2 zsets with 4 members (00.02% of keys, avg size 2.00)

如果你担心这个指令会大幅抬升 Redis 的 ops 导致线上报警,还可以增加一个休眠参数。

  ...