运维人生

记录一些点点滴滴 - 粤ICP备14078943号-1

golang连mysql设置超时

1、未使用代理

    dsn := "username:password@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

db, err := gorm.Open(mysql.New(mysql.Config{
	DSN:                       dsn,
	DefaultStringSize:         256,
	DisableDatetimePrecision:  true,
	DontSupportRenameIndex:    true,
	DontSupportRenameColumn:   true,
	SkipInitializeWithVersion: false,
}), &gorm.Config{
	Dialector: &MyDialector{
		ctx: ctx,
	},
})
if err != nil {
	panic(fmt.Sprintf("Failed to connect to database: %v", err))
}
defer db.Close()

// 使用数据库连接进行操作...

2、使用了代理

    dialer, err := proxy.SOCKS5("tcp", s.opt.Dbsocks, auth, proxy.Direct)
if err != nil {
	logs.Error("initDBProxyUrl:%s %v", s.opt.Dbsocks, err)
	return err
}

proxyTimeout := time.Duration(config.Data().Kgmysql.ProxyConTimeout) * time.Millisecond

// 此处自定义一个拨号(代理)
myDialContext := func(ctx context.Context, addr string) (net.Conn, error) {
	ctx, cancel := context.WithTimeout(ctx, proxyTimeout)
	defer cancel()
	con, err := dialer.DialContext(ctx, "tcp", addr)
	// con, err := dialer.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}
	return con, err
}
mysqlDriver.RegisterDialContext("fixieDial", myDialContext)
logs.Info("createNewConnection before gorm.Open: %v", err)

db, err := gorm.Open(gormMysql.Open(dbUrl), &gorm.Config{})

   其中这里con, err := dialer.DialContext(ctx, "tcp", addr) 这个需要修改源码
   golang.org/x/net/proxy
   proxy.go这里

// A Dialer is a means to establish a connection. // Custom dialers should also implement ContextDialer. type Dialer interface {

// Dial connects to the given address via the proxy.
Dial(network, addr string) (c net.Conn, err error)
// DialContext connects to the given address via the proxy using
// the provided context. 这个是新定义的
DialContext(ctx context.Context, network, addr string) (net.Conn, error)

}

阅读原文

从实例看健康教育与促进工作理念(市II类 2.0)学分

最近开始学习

《从实例看健康教育与促进工作理念》市II类 2.0学分,共10道题

答案如下:

新时期我国健康促进工作面临的任务及政策解读

1)健康促进法》不含哪项规定 A 2)不低于() B 3) 哪一项不准确 D 4) 的工作主体是 C 5) 那一项含义更准确 B 2. 从科研科普实例看健康教育项目运筹思路

1) 教育相关领域的项目 E 2) 考虑将以下哪个因素作为有鲜明学科特征的内容 C 3) 于高质量成果的发表 E

  1. 浅谈专业知识与大众的科学普及

1)专业的科普工作,需要 E

2)科普文章,要点是 E

3)下列不正确的一项是A

  1. 讲好故事!新冠大背景下的卫健宣传报道

1)要把握的是 E

2)报道时,要注意 E

3)闻的属性包括 E

4)作,以下对的是 E

5)题材的好稿件 E

  1. 健康传播工作中新媒体的最大化利用

1)我们现在要做的是 E

2)量越来越多,要注意 E

3)体稿件,要注意的是 E

4)标题具备的特点是 E

5)息需要满足受众( )的需求 E

  1. 健康教育与健康促进领域常用的研究方法——调查研究

1)评的三个主要方面是 B

2)计的主要区别在于 D

3) 方法中,抽样误差最小的是 D

  1. 健康教育与健康促进领域常用的研究方法——实验研究

1)机化分组的目的是 D 2)中,设立对照是为了 C 3) 计的基本原则有 A

  1. 健康教育与健康促进领域常用的统计分析方法

1)一般、不满意、非常不满意),应选 D

2)主要目的是比较 A

3) 量,其中定量变量是 A

  1. 基层科研资料的来源及论文的撰写

1)主要特点不包括 B

2)不属于直接资料 D

3)性有效论文包括 E

4)要通常不含有 C

  1. 如何撰写健康促进优秀实践案例

1)进实践案例不需要 C

2)例撰写步骤不包括 E

3)践的特征不包括 A

复制链接浏览器打开 也可快速学习

http://course.gameyeah.net/pages/course/index

阅读原文

mongodb分片和片键

mongodb优势 提供分布式存储解决方案,只需要简单配置即可; 达到了分散写入,集中查询的好处,方便扩展

json格式操作与存储,无需在意数据的存储格式,不像关系数据库那样麻烦

提供有比较完整的关系数据库sql查询操作,虽未测试过,官方与网络说可以支持上十亿的数据存储与读取,而速度得到保证。

官网说还直接支持MapReduce,这个完全值得去研究研究

其实mongodb的不足之处也很明显,比如数据一致性得不到保证,写入会出现失败,占磁盘空间等等,完全不适合做业务开发

但是用于日志采集存储分析处理,我完全可以容忍偶尔的数据遗漏;我追求的是方便快速写入与查询。

片键 chunk(块)为分片中最小存储单位,是一个数据集合。

一个片上有多个chunk,一个chunk只能存在于一个分片上面。

数据就是根据片键划分到各分片上面的chunk中的,比如说:{{"Wid":10000}-->>{"Wid":10010}},这就是一个块,Wid就是我们要说的片键,是一个表中的某个字段。

查询的时候也是按照这个字段去查询,相当于关系数据库中分库分表的作用。

需求 查询局部化 意思就是我每次查询只需要到某一个分片上去取数据就可以了,这样子会快。

数据均衡性 数据划分均衡存储到各台机子上面,不能过于集中,这样会导致某台机器读写瓶颈,影响速度

所以为了达到这个目的,片键必须设置好。

注意或原则 片键必须是一个索引,即使用片键做索引

片键通常由两个字段组成,第一个是粗粒度,第二个是粒度较细,即采用复合片键

片键选择 怎样选择:

小基数片键:如果某个片键一共只有N个值,那最多只能有N个数据块,也最多只有个N个分片。则随着数据量的增大会出现非常大的但不可分割的chunk。如果打算使用小基数片键的原因是需要在那个字段上进行大量的查询,请使用组合片键,并确保第二个字段有非常多的不同值。

随机片键:随机片键(比如MD5)最终会使数据块均匀分布在各个分片上,一般观点会以为这是一个很好的选择,解决了递增片键不具有写分散的问题,但是正因为是随机性会导致每次读取都可能访问不同的块,导致不断将数据从硬盘读到内存中,磁盘IO通常会很慢。

递增的片键:使用递增的分片的好处是数据的“局部性”,使得将最新产生的数据放在一起,对于大部分应用来说访问新的数据比访问老的数据更频繁,这就使得被访问的数据尽快能的都放在内存中,提升读的性能。这类的片键比如时间戳、日期、ObjectId、自增的主键(比如从sqlserver中导入的数据)。但是这样会导致新的文档总是被插入到“最后”一个分片(块)上去,这种片键创造了一个单一且不可分散的热点,不具有写分散性。

准升序键加搜索键: 通过像{coarselyAscending:1,search:1}这样的组合片键来实现,其中coarselyAscending的每个值最好能对应几十到几百个数据块,而search则应当是应用程序通常都会一句其进行查询的字段。

注意:serach字段不能是升序字段,不然整个复合片键就下降为升序片键。这个字段应该具备非升序、分布随机基数适当的特点。 复合片键中的第一个字段保证了拥有数据局部性,第二字段则保证了查询的隔离性。 首先一个大数据块((-∞,-∞),(∞,∞)),当他被填满,MongoDB将自动分割成两块,比如:

((-∞,-∞),("2012-07","susan"))

[("2012-07","susan"),(∞,∞)) 假设现在还是7月,则所有写操作会被均匀的分布到两个块上。所有用户名小于susan的数据被写入块1中,所有大于susan的数据被写入块2,然后整个生态系统就良性运行了,等到8月,MongoDB又开始创建2012-08的块,分布还是均衡的(这里不是时时均衡,肯定有个抹平的过程),等到9月,7月的数据无人访问就开始退出内存,不再占用资源。

测试 插入

如上文所描述设置 正确的分键再插入数据,对后面的查询非常重要!

图片

把添加卡顿率数据到mongo集群

10.1.3.22:10100[1]> get "201603240728|167838166|liaoning|unicom|-" "{\"totalCount\":\"10\",\"user_count\":\"8\",\"bufCnt_not_none\":0,\"buf_user_Count\":0,\"bufCnt_sum\":0}" 分析: 如果使用单一片键的话存在以下问题:

要求访问新的数据比访问老的数据更频繁 -- 可用 时间戳、日期、ObjectId、自增的主键 --- 但是不是写分散

要使数据块均匀分布在各个分片 -- 可用md5 -- 但是 导致不断将数据从硬盘读到内存中,磁盘IO通常会很慢

所以我们使用复合片键,即 {coarselyAscending:1,search:1}

1) 从时间串抽出天日期 做coarselyAscending值,即 $time_day = substr("201603240728", 0, 8)

2) 需要一个类GUID的随机数,还要常查询的 。 目前没有, 用 167838166|liaoning|unicom 做md5值, 或者直接用loc值

于是

db.apm_web_kpi.ensureIndex({'time_day': 1, 'loc': 1}) db.runCommand( { shardcollection : "kstat.apm_web_kpi", key:{"time_day":1, "loc":1}}); 测试时间: 日志数据原来是插入redis的, 使用0.058s即58ms; 添加插入mongo的代码,最小总共使用0.095s即95ms, 增长30ms左右; 不过有时高达0.507s,即最高增长为0.5s左右。

插入数据也快

[root@ ...Stream]# cat /data/logs/Stream-access_20160623123.log|grep apm|awk '{print $19}' | awk '{sum+=$1} END {print "Average = ", sum/NR}' Average = 0.0636 [root@ ...Stream]# cat /data/logs/Stream-access_20160623153.log|grep apm|awk '{print $19}' | awk '{sum+=$1} END {print "Average = ", sum/NR}' Average = 0.2406#后来发现是由于164这个分片通信问题导致的部分花时较长,把164分片权重降低后(或不连164),速度有质的飞越(平均只花了30ms) ---- 可能与redis保存一样快!! cat /data/logs/Stream-access_20160623172*.log|grep apm|awk '{print $19}' | awk '{sum+=$1} END {print "Average = ", sum/NR}' Average = 0.0908 有三台机器,三个查询入口,根据权重随机选取连接插入,这样能够达到插入负载均衡。

使用 printShardingStatus(db.getSisterDB("config"),1);

把原来的容灾日志保存到mongodb中。原数据每分钟产生230左右条数据.

原来源始数据存放于redis中,如下:

10.1.3.22:10100[2]> get "rg_201606211428|10.1.80.173|d.k.com|-|-""{\"costtime\":\"89.837\",\"request\":\"107\",\"success\":\"98\",\"request_all\":\"107\",\"flow\":\"22730.000\"}"

根据上面描述,为了保证查询速度,这里以 月时间 + 数据时间分钟值 作为片键索引

db.recover_gateway.ensureIndex({'data_month' => 1, 'data_time' => 1}) db.runCommand( { shardcollection : "kstat.recover_gateway", key:{"time_month":1, "data_time":1}}); 插入数据,到目前为止,数据量为60万,查询分片信息,数据块被分得还算是均衡的

插入速度也比较快

[root@ ...Stream]# cat /data/logs/FanxingStream-access_20160623123.log|grep recover|awk '{print $20}' | awk '{sum+=$1} END {print "Average = ", sum/NR}' Average = 0.0295071 [root@ ...Stream]# cat /data/logs/FanxingStream-access_20160623153.log|grep recover|awk '{print $20}' | awk '{sum+=$1} END {print "Average = ", sum/NR}' Average = 0.115879

后来发现是由于164这个分片通信问题导致的部分花时较长,把164分片权重降低后(或不连164),速度有质的飞越(平均只花了20ms) ---- 可能与redis保存一样快!!

cat /data/logs/Stream-access_20160623172*.log|grep recover|awk '{print $20}' | awk '{sum+=$1} END {print "Average = ", sum/NR}' Average = 0.0479784 此时当我想再次设置唯一主键时,报错: ---

原因: 唯一索引问题 如果集群在_id上进行了分片,则无法再在其他字段上建立唯一索引 MongoDB无法保证集群中除了片键以外其他字段的唯一性

查询

有三台机器,三个查询入口,根据权重随机选取连接查询

// ----- 如果未完全使用复合片键索引操作 ----

//31万,耗时0.275秒

//60万,耗时0.729秒

//84万, 耗时0.955秒

// ----- 如果完全使用到了复合片键操作 ----

//31万,耗时0.01秒

//60万,耗时0.024秒

//84万, 耗时0.104秒

总结: 一个理想的片键可以极大的提升CRUD的性能,充分利用分片的优势。

后续继续观察测试上百万上千万数据的读写性能。

阅读原文