原文链接:golang 并发demo 写入 redis
源代码:
package main
import (
"fmt"
"runtime"
"strconv"
"time"
"gopkg.in/redis.v3"
)
var (
jobnum = runtime.NumCPU()
//每次写入redis的数量
//除以 jobnum 为了保证改变了任务数, 总量不变, 便于测试
procnum = 100000 / jobnum
)
type Job struct {
ID string
Client *redis.Client
Result chan<- string
}
func waitJobs(dones <-chan struct{}, results chan string) {
working := jobnum
done := false
for {
select {
case result := <-results:
println(result)
case <-dones:
working--
if working <= 0 {
done = true
}
default:
if done {
return
}
}
}
}
func initClient(poolSize int) *redis.Client {
client := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
DialTimeout: time.Second,
ReadTimeout: time.Second,
WriteTimeout: time.Second,
PoolSize: poolSize,
Password: "123.com",
DB: 0,
})
if err := client.FlushDb().Err(); err != nil {
panic(err)
}
return client
}
func main() {
start := time.Now()
fmt.Println("start:", start)
defer func() {
end := time.Now()
fmt.Println("end:", end)
fmt.Println("jobs num:", jobnum, "total items:", jobnum*procnum)
fmt.Println("total seconds:", end.Sub(start).Seconds())
}()
//任务channel 定义缓冲器为job数量
jobs := make(chan Job, jobnum)
//存放结果
results := make(chan string, jobnum*procnum)
//每个任务完成之后给dones发送一次
dones := make(chan struct{}, jobnum)
client := initClient(10)
defer client.Close()
//定义每个任务执行的方法
jobfunc := func(client *redis.Client, id string) (string, error) {
defer func() {
//完成之后向 dones 发送数据
dones <- struct{}{}
//fmt.Println("job id:", id, "完成")
}()
//写入 procnum 条数据
for idx := 0; idx < procnum; idx++ {
key := id + "-" + strconv.Itoa(idx)
_, err := client.Set(key, time.Now().String(), 0).Result()
if err != nil {
return "", err
}
//fmt.Println("key:", key, " | result:", val, " | error:", err)
}
return "ok", nil
}
//1 添加 job 到 channel
go func() {
for index := 0; index < jobnum; index++ {
jobs <- Job{strconv.Itoa(index), client, results}
}
defer close(jobs)
}()
//2 并行执行 jobs
for j := range jobs {
go func(job Job) {
jobfunc(client, job.ID)
job.Result <- "ok"
}(j)
}
//3 等待所有任务完成
waitJobs(dones, results)
}
知识兔运行结果:
[root@localhost 111]# go run redis.go
start: 2019-09-24 08:26:34.614166323 +0000 UTC m=+0.001802059
ok
ok
ok
ok
ok
ok
ok
ok
end: 2019-09-24 08:26:35.655656884 +0000 UTC m=+1.043292369
jobs num: 8 total items: 100000
total seconds: 1.04149031
知识兔8 个 goroutine: 1s 完成10w数据写入