本文基于Redis最新unstable版本下,执行info命令后,返回的各项指标进行解释。并对其中需要特别注意的指标进行指出说明。
并会对阿里云info进行简单对比。区分阿里云对info进行了哪些方面的改造。
《向上管理的艺术》小结
20%的向上管理,决定了80%的工作效率和工作成果。
在之前的一篇博客听《工作三年我学到了什么》总结提到的音频中,讨论者推荐了《向上管理的艺术》这本书。于是便买了(我才不会告诉你是凑单),利用了一周的睡前时间把它给读完,在读的过程中,回想自己这一年半的工作经历,的确是在无意间触犯到了好几条禁忌行为。。。感谢领导的包容和支持。
利用周末空余时间将这本书做个简单的总结,尽量从自身层面优化。不仅是与领导沟通,在生活中也处处需要注意。
一个人的汇报反馈机制,往往能影响到上司对你的态度和看法。上司也有自己的事要做,并不会时时刻刻的盯着你;
领导负责下发任务,如果没有反馈,那么他将无法掌控任务的进度,甚至最终因没有反馈而导致任务失败,则会大大降低领导对你的看法。
领导的经验摆在那,有很多在我们看来比较困难的事,也许领导几句话、一个想法、一个电话就能轻松的解决。领导在一定意义上,也是我们的资源。
领导也是一个人,也会有各种各样的性格和情绪。如何在合适时机、选择合适方式才式获取到到正反馈信息?这不仅仅跟领导反馈,在生活中,这也是一门需要时时需要注意的地方。
毕竟是有求于人,往往就是那么一个不经意的小点,导致了事情的失败,影响的只会是自己,徒增非常多的人力物力。
多站在别人的角度上思考,别人是怎么看待这件事,需要我做什么,希望我怎么做。才能以更好的姿势、更快的效率去做好一件事。
MySQL参数之innodb_fast_shutdown、innodb_force_recovery
innodb_fast_shutdown
MySQL在平时工作时,会将大量的数据都保存在内存当中。那么在关闭的时候,什么东西需要持久化?什么东西不需要持久化呢?
在MySQL中,innodb_fast_shutdown
参数控制着关闭行为。它的可取值有0、1、2。
顾名思义,fast_shutdown,0表示不需要快速关闭、1需要快速关闭。
- 0:在关闭时需要将内存与磁盘中数据不一致的数据页都进行刷盘行为。主要包含有:
- 删除无用的undo页。
- 将log buffer中的日志都flush到log files。
- merge change buffer。
- flush dirty page
- 1:在关闭时,只进行刷新脏页行为。不需要purge all、merge change buffer。
- 2:在关闭时,只进行flush log buffer。不需要purge all、merge change buffer、flush dirty。
注意
- 在进行大版本升级时,需要将该参数设置为0
- 该参数默认值为1
- 该参数设置为2时,下次重启将会做
crash recovery
行为
innodb_force_recovery
有的时候由于MySQL在关闭前存在一些重操作行为,导致MySQL启动需要消耗大量的时间,但是我们需要能够尽可能快速的启动MySQL服务。
MySQL提供了参数innodb_force_recovery
来规定MySQL启动过程中需要做的行为动作。
该参数可选值为0~6,当该参数设置值大于0时,可以对表执行select、create、drop操作,但insert、update或者delete这类操作是不允许的。
- 0:表示恢复时执行所有的恢复操作。
- 1:(SRV_FORCE_IGNORE_CORRUPT)忽略检查到的corrupt页
- 2:(SRV_FORCE_NO_BACKGROUND)阻止主线程的运行,如主线程需要执行full purge操作,会导致crash
- 3:(SRV_FORCE_NO_TRX_UNDO)不执行事务回滚操作
- 4:(SRV_FORCE_NO_IBUF_MERGE)不执行插入缓冲的合并操作
- 5:(SRV_FORCE_NO_UNDO_LOG_SCAN)不查看撤销日志(Undo Log),InnoDB存储引擎会将未提交的事务视为已提交
- 6:(SRV_FORCE_NO_LOG_REDO)不执行前滚的操作
MySQL参数之innodb_autoinc_lock_mode
insert种类
在讲innodb_autoinc_lock_mode
参数之前,我们先来了解下MySQL insert的种类
- simple insert:插入的记录行数是确定的。比如:insert into、replace
- bulk insert:插入的记录行数不能马上确认的。比如:insert…select、replace…select、load data
- mixed-mode insert:也是’simple insert’,但是语句插入中存在没指定自增值的行。比如:INSERT INTO t1 (c1,c2) VALUES (1,’a’), (NULL,’b’), (5,’c’), (NULL,’d’)、INSERT … ON DUPLICATE KEY UPDATE
锁模式
在了解了以上insert种类后。我们来对innodb_autoinc_lock_mode
参数设置不同值时的表现进行描述。
传统模式
innodb_autoinc_lock_mode=0
这种模式性能最差,它会对所有的insert模式操作都去获取一个特殊的table-level auto-inc
。这种锁会持续到语句结束,以确保执行的insert语句以可预测且可重复的顺序分配自动递增值。这种模式更多是为了兼容老版本的MySQL运行。
MySQL参数之slow相关
MySQL的慢日志是MySQL提供的一种日志记录手段,能够将满足一定条件的语句给保存下来,能够很方便的进行针对化优化行为。
在MySQL中,主要有以下一些参数能够进行控制:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16+----------------------------------------+-------+
| Variable_name | Value |
+----------------------------------------+-------+
| log_slow_admin_statements | OFF |
| log_slow_slave_statements | OFF |
| slow_launch_time | 2 |
| slow_query_log | ON |
| slow_query_log_file | |
| tokudb_disable_slow_alter | OFF |
| tokudb_disable_slow_update | OFF |
| tokudb_disable_slow_upsert | OFF |
| min_examined_row_limit | 0 |
| log_queries_not_using_indexes | OFF |
| log_throttle_queries_not_using_indexes | 0 |
| long_query_time | 10 |
+-------------------------------+----------------+
- slow_query_log:是否开启慢日志统计功能
- long_query_time:命令执行时间阈值。默认是10s,这个时间指的是具体执行时间,不包含等锁时间
- slow_query_log_file:慢语句记录文件名。默认为数据文件目录,hostname-slow.log
- min_examined_row_limit:扫描超过这个值的语句才被记录
- log_queries_not_using_indexes:是否记录未使用索引的语句
- log_throttle_queries_not_using_indexes:每秒钟记录未使用索引语句的条数上限
- log_slow_admin_statements:是否记录optimize table,analyze table和alter table语句
- log_slow_slave_statements:是否记录slave产生的慢查询
- slow_launch_time:如果创建线程的时间超过这个值,则服务器状态变量
Slow_launch_threads
增加1。与慢语句无关 - tokudb%:这些参数是tokudb引擎特有的一些参数,在阿里云RDS实例中会默认安装。
https://www.docs4dev.com/docs/zh/mysql/5.7/reference/slow-query-log.html
https://www.docs4dev.com/docs/zh/mysql/5.7/reference/server-system-variables.html
Redis RDB文件存储格式
Redis存在两种数据文件:RDB和AOF。
AOF文件的结构比较简单,就不做说明。主要是简介RDB数据文件的结构
*.rdb文件是表示Redis瞬间快照的一个二进制文件。根据这个快照文件,可以将Redis恢复到Redis当时的状态。
rdb文件针对读写进行了优化操作。尽可能的会使用LZF压缩算法来减少文件的大小。
在命令行下我们可以通过od -x rdb.rdb | less
和od -c rdb.rdb | less
命令查看16进制和字符模式下的rdb文件。
注意:使用od -x
命令查出来的16进制是逆序的。
RDB文件结构
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
42
43
44
45
46
47
48
49
50
51
52
53
54----------------------------# RDB文件是二进制的,所以并不存在回车换行来分隔一行一行.
52 45 44 49 53 # 以字符串 "REDIS" 开头
30 30 30 36 # RDB 的版本号,大端存储,比如左边这个表示版本号为0006
----------------------------
FE 00 # FE = FE表示数据库编号,Redis支持多个库,以数字编号,这里00表示第0个数据库
----------------------------# Key-Value 对存储开始了
FD $length-encoding # FD 表示过期时间,过期时间是用 length encoding 编码存储的,后面会讲到
$value-type # 1 个字节用于表示value的类型,比如set,hash,list,zset等
$string-encoded-key # Key 值,通过string encoding 编码,同样后面会讲到
$encoded-value # Value值,根据不同的Value类型采用不同的编码方式
----------------------------
FC $length-encoding # FC 表示毫秒级的过期时间,后面的具体时间用length encoding编码存储
$value-type # 同上,也是一个字节的value类型
$string-encoded-key # 同样是以 string encoding 编码的 Key值
$encoded-value # 同样是以对应的数据类型编码的 Value 值
----------------------------
$value-type # 下面是没有过期时间设置的 Key-Value对,为防止冲突,数据类型不会以 FD, FC, FE, FF 开头
$string-encoded-key
$encoded-value
----------------------------
FE $length-encoding # 下一个库开始,库的编号用 length encoding 编码
----------------------------
... # 继续存储这个数据库的 Key-Value 对
FF ## FF:RDB文件结束的标志
8 byte checksum ## 8位校验码
------------------------------------
od -x rdb.rdb | head -n 10
0000000 4552 4944 3053 3030 fe36 fc1e ae47 2160
0000020 016e 0000 2800 6c65 7361 6974 5f63 3036
0000040 3930 3562 6432 3139 3962 3233 3134 3138
0000060 6338 3031 3338 6166 6233 3163 6264 5d4e
0000100 8b1f 0008 0000 0000 ff00 9bcc 535b 595a
0000120 c79b 66fb e7ae a42b 1db8 7585 7bde dea7
0000140 a779 eb62 7264 3500 e931 2a1c 2165 116c
0000160 6082 1838 27b5 1855 8b4d fb67 d18d 6344
0000200 3a62 6231 51b7 6dd3 6247 bb50 9aac b9ab
0000220 8f9c d610 7366 af95 b530 cd01 d906 8104
-------------------------------------
od -c rdb.rdb | head -n 10
0000000 R E D I S 0 0 0 6 376 036 374 G 256 ` !
0000020 n 001 \0 \0 \0 ( e l a s t i c _ 6 0
0000040 0 9 b 5 2 d 9 1 b 9 3 2 4 1 8 1
0000060 8 c 1 0 8 3 f a 3 b c 1 d b N ]
0000100 037 213 \b \0 \0 \0 \0 \0 \0 377 314 233 [ S Z Y
0000120 233 307 373 f 256 347 + 244 270 035 205 u 336 { 247 336
0000140 y 247 b 353 d r \0 5 1 351 034 * e ! l 021
0000160 202 ` 8 030 265 ' U 030 M 213 g 373 215 321 D c
0000200 b : 1 b 267 Q 323 m G b P 273 254 232 253 271
0000220 234 217 020 326 f s 225 257 0 265 001 315 006 331 004 201
pika学习之同步篇
- pika支持m-s的复制方式,跟redis主从复制命令一样,通过slave执行slaveof命令来触发。
- slave的trysync线程向master发起trysync,同时将同步位点信息发送给master
- master处理trysync命令,发起对slave的同步过程,从同步点开始顺序发送binlog或进行全同步
全量同步
pika在需要进行全量同步的时候,会将数据文件进行dump后通过rsync的deamon模式发送给slave。
实现逻辑
- slave在trysnc前启动rsync进程启动rsync服务
- master发现需要全同步时,判断是否有备份文件可用,如果没有先dump一份
- master通过rsync向slave发送dump出的文件
- slave用收到的文件替换自己的db
- slave用最新的偏移量再次发起trysnc
- 完成同步
何为IO多路复用
网络编程概念
在网络当中,数据的传输是基于HTTP/TCP协议簇来实现的。TCP协议仅仅是把这些数据看做是一串二进制流来进行处理。
所以:客户端和服务器是通过在建立的连接上发送字节流来进行通信
一个连接由它两端的套接字地址唯一确定,结构为(客户端地址:客户端端口号,服务端地址:服务端端口号)
。有了通信双方的连接地址信息后,就可以进行数据传输了。
在Unix系统中,实现了一套套接字接口来描述和规范双方通信的整个过程。
创建->连接->绑定->监听->响应
- socket():创建一个套接字描述符
- connect():客户端通过调用connect函数来建立和服务器的连接
- bind():告诉内核将socket()创建的套接字与某个服务端地址与端口连接起来,后续会对这个地址和端口进行监听
- listen():告诉内核,将这个套接字当成服务器这种被动实体来看待(服务器是等待客户端连接的被动实体,而内核认为socket()创建的套接字默认是主动实体,所以才需要listen()函数,告诉内核进行主动到被动实体的转换)
- accept():等待客户端的连接请求并返回一个新的已连接描述符
提问的智慧
在你提问之前
- 尝试在你准备提问的论坛的旧文章中搜索答案
- 尝试上网搜索以找到答案
- 尝试阅读手册以找到答案
- 尝试阅读常见问题文件(FAQ)以找到答案
- 尝试自己检查或试验以找到答案
- 向你身边的强者朋友打听以找到答案
- 如果你是程序开发者,请尝试阅读源代码以找到答案
当你提问时
- 慎选提问的论坛
- Stack Overflow
- 网站和 IRC 论坛
- 第二步,使用项目邮件列表
- 使用有意义且描述明确的标题
- 使问题容易回复
- 用清晰、正确、精准并合法语法的语句
- 使用易于读取且标准的文件格式发送问题
- 精确地描述问题并言之有物
- 话不在多而在精
- 别动辄声称找到 Bug
- 低声下气不能代替你的功课
- 描述问题症状而非你的猜测
- 按发生时间先后列出问题症状
- 描述目标而不是过程
- 别要求使用私人电邮回复
- 清楚明确的表达你的问题以及需求
- 询问有关代码的问题时
- 别把自己家庭作业的问题贴上来
- 去掉无意义的提问句
- 即使你很急也不要在标题写紧急
- 礼多人不怪,而且有时还很有帮助
- 问题解决后,加个简短的补充说明
听《工作三年我学到了什么》总结
最近听到一篇文章,觉得其中很多的点给了我很多收获。所以反复听了很多遍,并做了大概的总结。关键词:沟通、尝试、上升、思考、落地。
- 不要把自己局限于某一个位置,试着多尝试不同的东西,“管理”好自己,“管理”好身边的人。
- 你的技术能力决定了你能多快去完成目标。而你的非技术能力决定了你在朝哪个方向努力。