更好使用开发工具
这是在团队内部做的一个分享,PPT见附件
- 键盘设置
- 开发工具集合
- Bash/Zsh快捷键
- iTerm自定义快捷键
- iTerm快捷键
- 更好的展示git diff
- 更好的搜索代码the_silver_search
- Sublime Text快捷键 & Sublime Text设置
- IntelliJ IDEA插件 & 快捷键
- Chrome插件
- Sequel Pro插件 & console窗口的使用
- alias
这是在团队内部做的一个分享,PPT见附件
在做技术分享的时候,经常需要去展示自己的代码;下面是整理的需求:
放大局部代码
优点:
缺点:
1、打开IDEA的演示模式 View - Enter Presentation Mode
,截图放入Keynote
2、第二张幻灯片放大代码图片, 添加两个形状,遮挡不需要展示的代码
3、设置效果神奇移动
优点:
缺点:
1、安装代码高亮工具
brew install highlight
2、copy代码或者创建需要展示的代码文件
# 如果是copy的代码
# 注意需要指定 --syntax 扩展名
# -u 编码,否则中文会乱码
# -t 最好将代码中的tab转换成空格,keynote中\t的展示宽度可能会不一致
pbpaste | highlight --syntax=sh --style=github -k "Fira Code" -K 18 -u "utf-8" -t 4 -O rtf | pbcopy
# 如果是文件中的代码
highlight --style=github -k "Fira Code" -K 18 -u "utf-8" -t 4 -O rtf <filename> | pbcopy
3、直接在keynote中粘贴代码
4、设置效果神奇移动
如果使用过 asciidoc,对这个应该不陌生
If-Modified-Since
If-None-Match
Last-Modified
Cache-Control
ETag
Expires
具体可以查看这篇文章中的附件 媒体中心设计分享
CSI: 指利用ajax等技术,将动态的数据使用异步的方式加载进页面 (比较适用于PC, H5)
SSI: 通常url后缀为shtml
ESI: 最具代表性的 varnish/ats (比较适用于App的接口)
具体可以查看这篇文章:页面静态化
上面的几种方案都需要走到后端的服务器,在并发和加载速度要求比较高的情况下,可以选择生成静态文件上传到cdn
多级缓存可以降低中心缓存服务器的压力,但是也会存在数据不一致的问题
当当网交易链路:简单的将local cache的过期时间设置为1分钟,降低缓存不一致的概率 (适用于一致性要求不高的情景)
缓存击穿的几种场景:
对于场景1,为避免瞬时流量将db和缓存击垮,可以使用一个锁,保证并发环境下,只有1个/少量线程写入同一条数据
对于场景2,可以使用empty object,在存取缓存的时候将其替换为null,如果为了池子中有效数据留存率,可以将empty object和正常数据分开存放
对于场景3,需事先脱离缓存,db裸压,保证在没有缓存的情况之后可以正常支持线上的流量 (可忍受的RT内)
对页面的局部更新,不过会将当前url塞到浏览器的历史记录中
具体可以查看这篇文章:slim框架中pjax的实现
利用服务器端的输出缓存,输出部分页面
在一台机器存不下1个业务所有缓存的时候,一般都会选择分片的策略(大多采用取模的办法),但有的时候缩减单个缓存对象的大小,也可以节省整个池子的资源
防止订单Id号泄露每日流水,暴露商业机密;需要对订单Id号进行相应的处理,但是订单号的生成又需要满足以下条件
# | 平台 | rule | 来源 |
---|---|---|---|
1 | 大众点评 | 时间戳+用户标识码+随机数 | 大众点评订单系统分库分表实践 |
2 | 美团团购 | 单表自增Id * 100 + 买家Id后2位 | 美团团购订单系统优化记 |
3 | 淘宝 | 发号器Id + 买家Id后4位 | 淘宝在线交易数据演变 |
其他策略: 生产乱序码和真实的orderId关联
./ext_skel --extname=hank
cd hank
phpize
./configure
由于CLion目前还不支持MakeFile文件,所以要使用CMakeLists.txt进行中转
cmake_minimum_required(VERSION 3.3)
project(hank)
add_custom_target(makefile COMMAND make && make install
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
至此基本全部搞定,可以直接下断点,以debug模式进行调试
+-----------+
--> | counter 1 |
+-----------+
--> | counter 2 |
+-----------+ -> sum(subCounter)
--> | counter 3 |
+-----------+
--> | counter 4 |
+-----------+
在内部都有多个计数器,这样在并发更新对象的时候,随机选择一个,就可以将锁冲突的概率降低到 1/n
拿文章的喜欢计数来做例子,当有n个人同时点击喜欢的时候,INNODB会锁住这条记录,这篇文章的喜欢计数器将是串行增长的。
pre_posts
+-------+-----+----------+
| id | ... | favs |
+-------+-----+----------+
| 10000 | ... | 8001 |
+-------+-----+----------+
再看下面的,可以将喜欢数从 posts 表拆分出来,一个文章 id,对应多个子计数器,在更新计数器的时候,可以随机选择一条记录增加,在取文章喜欢数的时候,可以sum一下累加起来;这样就降低了并发时候的冲突。
pre_post_favs
+-----+----------+----------+
| id | post_id | favs |
+-----+----------+----------+
| 1 | 10000 | 2001 |
| 2 | 10000 | 1994 |
| 3 | 10000 | 2010 |
| 4 | 10000 | 1898 |
+-----+----------+----------+
显然上面的数据解决了数据并发写入的问题,但是查询的代价却是提高了,想到的办法就是对计数器进行缓存。
读取的时候被动缓存的话,就会产生计数器的延迟;所以这里可以采用 canal 监听 mysql binlog 主动触发 cache 的更新。
那么问题又来了,既然是存到 redis 中,该用什么类型的;如果使用大量的 string 的话,key 就会占用大量的内存,可以部分改用 hash,但是 redis 的设定中,只有 数量 < hash-max-ziplist-entries
的时候才会采用优化的存储方式;根据多位大牛的研究 1000 是比较合适的。
favs:10
000 -> 8001
001 -> 0
...
999 -> 0
当 数据量 和 qps/tps 达到一定的时候,将某块业务的一系列的表迁移到另外一个库是必然需要的。
+----------------------------------------------+
A | |
+----------------------------------------------+
++
B ||
++
+----------------------------------------------+------------+
A | | |
+----------------------------------------------+------------+
++ +------------+
B || | |
++ +------------+
可以一次dump 10条数据 (拍脑袋),对于更新比较频繁的表可以适当减少,这里会有少量的数据是不一致的 (表的并发更新之类,dump 不能保证原子性),不用担心,我们可以在后面校验数据的时候直接修复掉
对 id取模,多进程dump 加快速度
+----------------------------------------------+------------+
A | | |
+----------------------------------------------+------------+
+-------------+ +------------+
B | | | |
+-------------+ +------------+
这块要一条一条数据的进行对比 (扫表)
在业务代码里面,将 db 的连接改到新库 B 上
到这一步,代码里面的双写就可以直接去掉了;完美迁库。(旧库中的表不急忙删除,你懂的)
pre_messages
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| sender_id | int(11) unsigned | NO | | 0 | |
| message | varchar(255) | NO | | | |
| type | varchar(50) | NO | | | |
| expires_at | datetime | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
| deleted_at | datetime | YES | | NULL | |
+------------+------------------+------+-----+---------+----------------+
pre_message_recipients
+--------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| recipient_id | int(11) unsigned | NO | | 0 | |
| message_id | int(11) unsigned | NO | | 0 | |
| status | tinyint(1) unsigned | NO | | 0 | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
| deleted_at | datetime | YES | | NULL | |
+--------------+---------------------+------+-----+---------+----------------+
赤龙
汉尼拔
沉默的羔羊
异次元杀阵
异次元杀阵3:前传
异次元杀阵2:超级立方体
天堂电影院
海上钢琴师
西西里的美丽传说
蝙蝠侠:侠影之谜 Batman Begins (2005)
蝙蝠侠:黑暗骑士 The Dark Knight (2008)
蝙蝠侠:黑暗骑士崛起 The Dark Knight Rises (2012)
碟中谍 Mission: Impossible (1996)
碟中谍2 Mission: Impossible II (2000)
碟中谍3 Mission: Impossible III (2006)
碟中谍4 Mission: Impossible - Ghost Protocol (2011)
谍影重重 The Bourne Identity (2002)
谍影重重2 The Bourne Supremacy (2004)
谍影重重3 The Bourne Ultimatum (2007)
谍影重重4 The Bourne Legacy (2012)
洛奇 Rocky (1976)
洛奇2 Rocky II (1979)
洛奇3 Rocky III (1982)
洛奇4 Rocky IV (1985)
洛奇5 Rocky V (1990)
洛奇6:永远的拳王 Rocky Balboa (2006)
第一滴血 First Blood (1982)
第一滴血2 Rambo: First Blood Part II (1985)
第一滴血3 Rambo III (1988)
第一滴血4 Rambo (2008)
教父 The Godfather (1972)
教父2 The Godfather: Part Ⅱ (1974)
教父3 The Godfather: Part III (1990)
MacBook型号:13-inch, Mid 2012
SSD型号:Intel SSD 530 180G
工具:
釰 > 多功能组合螺丝刀套装
软件:
Trim Enabler
Carbon Copy Cloner
实践结果:
1. SSD只能放在主硬盘位,于是原来的机械硬盘就放在光驱位
2. 程序从机械硬盘上转移到SSD上之后,Chrome打开某些网页的时候存在问题,重新下载Chrome安装就可以了。
3. 貌似`Carbon Copy Cloner`不会copy空文件,所以,某些目录会显示成英文名字;直接执行
touch "/Users/$(whoami)/Desktop/.localized"
{
"cmd": ["php", "-f", "$file"],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.php"
}
{
"cmd": ["g++ -Wall ${file} -o ${file_base_name} && ${file_path}/${file_base_name}"],
"working_dir": "${file_path}",
"selector": "source.c++",
"shell": true
}
{
"cmd": ["lua52", "$file"],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.lua"
}
顺便,转换文件格式的地方View -> Line Endings
我愿化身石桥,受五百年风吹,五百年日晒,五百年雨打,但求那少女从桥上走过……