原文链接:golang 并发demo 写入 redis

源代码:

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "runtime"
  6. "strconv"
  7. "time"
  8.  
  9. "gopkg.in/redis.v3"
  10. )
  11.  
  12. var (
  13. jobnum = runtime.NumCPU()
  14. //每次写入redis的数量
  15. //除以 jobnum 为了保证改变了任务数, 总量不变, 便于测试
  16. procnum = / jobnum
  17. )
  18.  
  19. type Job struct {
  20. ID string
  21. Client *redis.Client
  22. Result chan<- string
  23. }
  24.  
  25. func waitJobs(dones <-chan struct{}, results chan string) {
  26. working := jobnum
  27. done := false
  28. for {
  29. select {
  30. case result := <-results:
  31. println(result)
  32. case <-dones:
  33. working--
  34. if working <= {
  35. done = true
  36. }
  37. default:
  38. if done {
  39. return
  40. }
  41. }
  42. }
  43. }
  44.  
  45. func initClient(poolSize int) *redis.Client {
  46. client := redis.NewClient(&redis.Options{
  47. Addr: "localhost:6379",
  48. DialTimeout: time.Second,
  49. ReadTimeout: time.Second,
  50. WriteTimeout: time.Second,
  51. PoolSize: poolSize,
  52. Password: "123.com",
  53. DB: ,
  54. })
  55. if err := client.FlushDb().Err(); err != nil {
  56. panic(err)
  57. }
  58. return client
  59. }
  60.  
  61. func main() {
  62. start := time.Now()
  63. fmt.Println("start:", start)
  64. defer func() {
  65. end := time.Now()
  66. fmt.Println("end:", end)
  67. fmt.Println("jobs num:", jobnum, "total items:", jobnum*procnum)
  68. fmt.Println("total seconds:", end.Sub(start).Seconds())
  69. }()
  70.  
  71. //任务channel 定义缓冲器为job数量
  72. jobs := make(chan Job, jobnum)
  73. //存放结果
  74. results := make(chan string, jobnum*procnum)
  75. //每个任务完成之后给dones发送一次
  76. dones := make(chan struct{}, jobnum)
  77.  
  78. client := initClient()
  79. defer client.Close()
  80.  
  81. //定义每个任务执行的方法
  82. jobfunc := func(client *redis.Client, id string) (string, error) {
  83. defer func() {
  84. //完成之后向 dones 发送数据
  85. dones <- struct{}{}
  86. //fmt.Println("job id:", id, "完成")
  87. }()
  88.  
  89. //写入 procnum 条数据
  90. for idx := ; idx < procnum; idx++ {
  91. key := id + "-" + strconv.Itoa(idx)
  92.  
  93. _, err := client.Set(key, time.Now().String(), ).Result()
  94. if err != nil {
  95. return "", err
  96. }
  97. //fmt.Println("key:", key, " | result:", val, " | error:", err)
  98. }
  99.  
  100. return "ok", nil
  101. }
  102.  
  103. //1 添加 job 到 channel
  104. go func() {
  105. for index := ; index < jobnum; index++ {
  106. jobs <- Job{strconv.Itoa(index), client, results}
  107. }
  108. defer close(jobs)
  109. }()
  110.  
  111. //2 并行执行 jobs
  112. for j := range jobs {
  113. go func(job Job) {
  114. jobfunc(client, job.ID)
  115. job.Result <- "ok"
  116. }(j)
  117. }
  118.  
  119. //3 等待所有任务完成
  120. waitJobs(dones, results)
  121. }

运行结果:

  1. [root@localhost ]# go run redis.go
  2. start: -- ::34.614166323 + UTC m=+0.001802059
  3. ok
  4. ok
  5. ok
  6. ok
  7. ok
  8. ok
  9. ok
  10. ok
  11. end: -- ::35.655656884 + UTC m=+1.043292369
  12. jobs num: total items:
  13. total seconds: 1.04149031

8 个 goroutine: 1s 完成10w数据写入

golang 并发demo 写入 redis的更多相关文章

  1. 高并发简单解决方案————redis队列缓存+mysql 批量入库(ThinkPhP)

    问题分析 问题一:要求日志最好入库:但是,直接入库mysql确实扛不住,批量入库没有问题,done.[批量入库和直接入库性能差异] 问题二:批量入库就需要有高并发的消息队列,决定采用redis lis ...

  2. Golang 并发简介

    并发概要 随着多核CPU的普及, 为了更快的处理任务, 出现了各种并发编程的模型, 主要有以下几种: 模型名称 优点 缺点 多进程 简单, 隔离性好, 进程间几乎无影响 开销最大 多线程 目前使用最多 ...

  3. golang 并发锁的陷阱

    错误代码示例 package main import ( "sync" "strconv" "fmt" ) type Node struct ...

  4. Golang - 并发编程

    目录 Golang - 并发编程 1. 并行和并发 2. go语言并发优势 3. goroutine是什么 4. 创建goroutine 5. runtime包 6. channel是什么 7. ch ...

  5. 4种Golang并发操作中常见的死锁情形

    摘要:什么是死锁,在Go的协程里面死锁通常就是永久阻塞了,你拿着我的东西,要我先给你然后再给我,我拿着你的东西又让你先给我,不然就不给你.我俩都这么想,这事就解决不了了. 本文分享自华为云社区< ...

  6. golang并发编程

    golang并发编程 引子 golang提供了goroutine快速实现并发编程,在实际环境中,如果goroutine中的代码要消耗大量资源时(CPU.内存.带宽等),我们就需要对程序限速,以防止go ...

  7. 马蜂窝搜索基于 Golang 并发代理的一次架构升级

    搜索业务是马蜂窝流量分发的重要入口.很多用户在使用马蜂窝时,都会有目的性地主动搜索与自己旅行需求相关的各种信息,衣食住行,事无巨细,从而做出最符合需求的旅行决策. 因此在马蜂窝,搜索业务交互的下游模块 ...

  8. 批量写入redis

    批量写入redis key := GetSeriesKey(series.Id) idNames = append(idNames, key, series.Name) == { err = Mset ...

  9. lua模块demo(redis,http,mysql,cjson,本地缓存)

    1. lua模块demo(redis,http,mysql,cjson,本地缓存) 1.1. 配置 在nginx.conf中设置lua_shared_dict my_cache 128m; 开启ngi ...

随机推荐

  1. Java 异常处理专题,从入门到精通

    内置异常和Throwable核心方法 Java内置异常 可查异常(必须要在方法里面捕获或者抛出) ClassNoFoundException 应⽤程序试图加载类,找不到对应的类 IllegalAcce ...

  2. Ansible部署zabbix-agent

    playbook目录 zabbix/ ├── hosts ##定义的主机列表 ├── install_zabbix_agent.yml ##安装入口文件 └── roles ├── install_z ...

  3. python(xlsxwriter模块使用)

    XlsxWriter简介XlsxWriter是一个Python模块,可用于在Excel 2007+ XLSX文件中写入多个工作表的文本,数字,公式和超链接.它支持格式化等功能.可到官网了解更多详情,官 ...

  4. java动态代理——字段和方法字节码的基础结构及Proxy源码分析三

    前文地址:https://www.cnblogs.com/tera/p/13280547.html 本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的 ...

  5. IDEA 修改快捷键和Myeclipse 快捷键一致

    介绍 我们知道IDEA这款开发工具功能很强大,为了简化开发步骤,提高开发效率,使用快捷键很显然是必不可少的,那么怎么才能使得IDEA快捷键和MyEclipse快捷键 保持相同呢? 第一种方法,一个快捷 ...

  6. Fortify Audit Workbench 笔记 Command Injection(命令注入)

    Command Injection(命令注入) Abstract 执行不可信赖资源中的命令,或在不可信赖的环境中执行命令,都会导致程序以攻击者的名义执行恶意命令. Explanation Comman ...

  7. 第七章 vuex专题

    一.Vuex安装 一般在创建项目是会选择 Vuex,如果没有选择: cnpm install vuex  --save 使用: import Vuex from "vuex"; V ...

  8. PDOStatement::getAttribute

    PDOStatement::getAttribute — 检索一个语句属性(PHP 5 >= 5.1.0, PECL pdo >= 0.2.0)高佣联盟 www.cgewang.com 说 ...

  9. 记502 dp专练

    趁着503的清早 我还算清醒把昨天老师讲的内容总结一下,昨天有点迷了 至使我A的几道题都迷迷糊糊的.(可能是我太菜了) 这道题显然是 数字三角形的变形 好没有经过认真思考然后直接暴力了 这是很不应该的 ...

  10. Vue通过Blob对象实现导出Excel功能

    不同的项目有不同的导出需求,有些只导出当前所显示结果页面的表格进入excel,这个时候就有很多插件,比如vue-json-excel或者是Blob.js+Export2Excel.js来实现导出Exc ...