-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.xml
239 lines (198 loc) · 25.2 KB
/
index.xml
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>皮智文的小宝库</title>
<link>http://edcismybrother.github.io/</link>
<description>Recent content on 皮智文的小宝库</description>
<generator>Hugo -- gohugo.io</generator>
<language>utf-8</language>
<lastBuildDate>Wed, 12 Dec 2018 00:00:00 +0000</lastBuildDate>
<atom:link href="http://edcismybrother.github.io/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>广度优先搜索</title>
<link>http://edcismybrother.github.io/bfs/</link>
<pubDate>Wed, 12 Dec 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/bfs/</guid>
<description>麻将胡牌算法(包括查听,查胡)
package main import ( &quot;fmt&quot; ) func main() { list := []int{11, 12, 13, 14, 14, 15, 16, 12} // lists := combination(list, []int{}) // for k, l := range lists { // fmt.Printf(&quot;组合:%v===&quot;, k) // for _, c := range l.combin { // fmt.Printf(&quot;类型:%v 值:%v;&quot;, c.tp, c.values) // } // fmt.Println() // } m := outTS(list) for k, v := range m { fmt.Printf(&quot;打出:%v,可以胡%v\n&quot;, k, v) } } func outTS(list []int) map[int][]int { var ts = make(map[int][]int, 0) out := make([]int, 0) if len(list)%3 !</description>
</item>
<item>
<title>redis集群学习</title>
<link>http://edcismybrother.github.io/redis/cluster/</link>
<pubDate>Fri, 30 Nov 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/redis/cluster/</guid>
<description>redis集群部署运行 以window为例子
首先修改配置文件 redis-cluster.conf
1、配置文件需要配置持久化类型,这里选择aof appendonly yes // 开启aof模式 appendfilename &quot;appendonly.7001.aof&quot; // aof名字 2、集群启动配置 cluster-enabled yes // 允许集群 cluster-config-file nodes-7001.conf // 集群配置文件,运行后自动生成 cluster-node-timeout 15000 // 集群节点响应超时 运行实例 进入redis目录下,运行redis-server.exe ./{&ldquo;配置文件路径&rdquo;}/name.conf 需要几个节点,就创建几个redis相关的配置文件,一般来说至少需要要3个master节点,每个主节点需要至少一个slave节点,因此至少需要6个节点 运行成功后只能算是开启了6个redis服务端,还不是集群
关联服务 6个服务端实例有了,就需要关联起来,通过使用 Redis 集群命令行工具 redis-trib 可以进行便携操作。 trib在redis源码中trib地址,将redis-trib.rb文件放到redis安装目录下。 trib是rb(rubby)类型文件,所以需要安装rubby运行环境,rubby安装地址。 在rubby目录下,安装redis驱动:gem install redis redis目录下运行:./redis-trib.rb create &ndash;replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005。
此时如果出现如下响应,表示集群关联成功。 Can I set the above configuration? (type &lsquo;yes&rsquo; to accept): yes(这里输入yes表示同意设置)
C:\Program Files\Redis&gt;redis-trib.rb create --replicas 1 127.</description>
</item>
<item>
<title>tcp异步</title>
<link>http://edcismybrother.github.io/tcp/sync/</link>
<pubDate>Wed, 14 Nov 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/tcp/sync/</guid>
<description>tcp异步框架学习 tao框架 evio框架
什么是同步异步 先讲讲同步,同步可以理解为串行,100个人要进入一个空间,可空间入口只有一个,这时候,人们只能排队进入,假设一个人进入需要费时1秒,100个就是100秒,人越多,效率就越低;这时候要解决效率的问题就需要用到异步了。 异步可以理解为并行,为每一个人开辟一个入口,这时候有n个人就会有n个入口,进入的时间永远就只需一秒,这样效率就大大提高了。
异步加锁的必要性 异步解决了进入效率的问题,但人们进入房间是需要做事情的,如果这个事件只是记忆某样东西,不对这个东西进行改变,这时候就没必要加锁,假如空间里面有一堆糖果,100个人里面有50个人的任务只是进来数当前糖果的,这时候就没必要加锁了,而另外50个人的任务是拿糖果,这就有必要加锁了。拿糖果这个任务可以分为两个步骤,先确认是否有糖果,有的话才拿,如果AB两个人通过要执行拿糖果的,AB都确认了有糖果,可是B比A手速要快,先一步把糖果全部拿走了,A再去拿的时候就拿不到了,这时候A的逻辑就会出问题了,他就会一直在那里拿糖果(可永远没有拿到的可能),但是加了锁就不一样了,锁相当于一个闸门,上锁后,只有一个人可以执行任务,其他人只能等待上个人执行完解锁后才能继续去抢锁执行任务。
线程池的概念 异步解决了效率的问题,使空间不再拥堵,但空间再大也会有上限,可是想要进入空间做事情的人是没有上限的,假设这个空间人气很高,一个庞大的人流量都想要进入这个空间做事,如果说为每个人都开辟一个通道,这时候这个空间将面临千疮百孔,濒临崩溃的局面。也许空间加糖果的例子可能还是有点抽象了,这里以银行为例子,银行相当于空间,每一个窗口相当于一个通道,事件相当于不同的业务,在人多的情况下,窗口越多,办理业务的效率也就越高,而对于银行来说,窗口也是有上限的,而且每开一个窗口都需要消耗一定资源(给窗口业务员发工资、窗口设备维护等等)。
线程池的具体设计 上面有提到过无限开启窗口的确定,就是资源消耗的递增,假设银行只有在每个月的最后一天人流量会暴增,为了这一天开启了很多个窗口来提高效率,可是其他的时间里,平均人流量很小,一到两个窗口就能应付,这时候其他的窗口就会无比空闲,假设你是一个精打细算的银行老板,你会容忍其他窗口的无所事事么,要知道维护这些空闲窗口是需要消耗的。 1. 设定一个合理的窗口数,不要为每一个人都开一个窗口,人多的话还是要进行排队,银行就是这样的。。。 2. 合理的窗口数虽然减少了开销,但是作为一个一毛不拔的我,还是觉得浪费了,毕竟在人流量极少的情况下,还是会有无所事事的窗口,这个时候就需要动态的增删窗口了;人流量小的时候,无所事事的窗口关闭,人流量多的时候,增加窗口,极多的时候,那就排队吧。
回归语言 任何事物都是讲究逻辑性的,语言也是符合上面两个例子的逻辑。空间、银行这些都可以看做我们的服务端,而来办理业务的人就是各种携带事件的tcp请求,而窗口就是routine(类型java线程,但比线程的创建消耗要小很多),业务就是你通过routine要异步处理的携带事件。
好的异步协程池 ants框架就是一个非常好用的,对上述所说的动态删减routine,控制routine上限,异步处理事件都有非常好的实现
以下就是个人参考ants框架的举例逻辑实现
// 主函数,模拟1000个事件,交给线程池异步处理,p就是协程池,限制上限10,通过push函数将任何丢到通道中 func main() { for i := 0; i &lt; 1000; i++ { // time.Sleep(2 * time.Millisecond) p.push(Msg{ from: uint64(i), data: &quot;haha&quot;, }) } fmt.Println(&quot;参与的worker数量:&quot;, len(p.workers)) time.Sleep(1 * time.Second) } //这里的push函数,导致的实际效果是每次是放一个事件进来等待空闲routine进行处理,一对多 //而ants作者的逻辑效果是一群事件在那里等待争抢空闲routine,多对多 //从逻辑性来开ants作者的逻辑效率会更高 type Pool struct { max uint64 workers []*Worker //存放工作者 chl chan Msg lock sync.</description>
</item>
<item>
<title>tcp长连接压测遇到的问题</title>
<link>http://edcismybrother.github.io/tcp%E9%95%BF%E8%BF%9E%E6%8E%A5%E5%8E%8B%E6%B5%8B/</link>
<pubDate>Tue, 13 Nov 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/tcp%E9%95%BF%E8%BF%9E%E6%8E%A5%E5%8E%8B%E6%B5%8B/</guid>
<description>tcp长连接压测遇到的问题 问题1:在大量长连接下,会出现很多拨号失败。 、、、 dial tcp 192.168.31.232:6001: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 、、、 拨号失败的问题在于服务端响应不及时 问题分析:在大量长连接同时请求时,出现了cpu、资源调用阻塞,很多的连接在等待分配 解决办法:轮询创建客户端加上延时
问题2:部分连接成功的客户端,会在请求的时候得不到相应的响应 目前的模拟客户端设置的时1分钟的超时,在5000长连接的压测下,30s的超时设置,会出现n个超时,1分钟的超时设置,超时的客户端会减少 问题分析:估计也是资源占用造成的问题 解决办法:加大服务器内核
问题3:部分连接成功的客户端,请求后被告知连接被远程端强制关闭,但服务端却没有主动关闭连接的操作 客户端已经dial成功,但通过返回的conn进行write和read操作被告知连接强制关闭,但服务端没有任何close迹象 原因分析:dial是在第二次握手的时候返回conn,而服务端accept是在第三次握手的时候返回conn,也就是说握手只进行到第二次握手, 这是因为握手的时候有两个队列,一个syn队列一个backlog队列(accept队列),一次握手,cli告诉ser要建立连接,第二次握手,ser通知 cli等待确认连接,这时连接状态进入syn队列,第三次握手,cli通知ser确认连接,连接状态进入backlog队列。 以上就是握手的过程,syn和backlog队列有限制,如果在大量并发连接出现,连接数超过backlog的长度的连接,将会阻塞在队列外,一定时间没有进入到backlog队列,连接将会被丢弃,这就出现了客户端dail成功,而服务端却没有accept。 解决办法:修改服务器内核配置,syn队列上限: /proc/sys/net/core/somaxconn;accept队列上限:/proc/sys/net/ipv4/tcp_max_syn_backlog</description>
</item>
<item>
<title>colly源码包分析</title>
<link>http://edcismybrother.github.io/colly/</link>
<pubDate>Tue, 30 Oct 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/colly/</guid>
<description>基本用法 infos := make([]info, 0) c := colly.NewCollector() c.OnHTML(&quot;.content div .rprt&quot;, func(e *colly.HTMLElement) { title := e.ChildText(&quot;.rslt p.title a&quot;) author := e.ChildText(&quot;.supp .desc&quot;) message := e.ChildText(&quot;.supp .details&quot;) pmid := e.ChildText(&quot;.aux .resc .rprtid dd&quot;) id, _ := strconv.ParseInt(pmid, 10, 64) i := info{ title: strings.TrimRight(title, &quot;.&quot;), author: author, message: message, pmid: id, } infos = append(infos, i) }) c.OnRequest(func(req *colly.Request) { log.Println(&quot;Visit:&quot;, req.URL.String()) }) c.Post(&quot;https://www.ncbi.nlm.nih.gov/pubmed&quot;, map[string]string{ &quot;term&quot;: &quot;kif15&quot;, &quot;p$a&quot;: strconv.</description>
</item>
<item>
<title>golang标准包分析---http</title>
<link>http://edcismybrother.github.io/tcp/%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/</link>
<pubDate>Wed, 17 Oct 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/tcp/%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/</guid>
<description>服务端 服务端是用来接收连接的,因此需要一个监听的逻辑
// 函数ListenAndServe用来开启服务并且监听,而这个 // 函数的核心就是tcp连接,通过net.Listen(param1,param2)得到listener // 其中param1是连接类型,可以有tcp,tcp4,tcp6......,param2则是服务地址:ip:port // 返回的listener是一个interface{}类型 type Listener interface { // Accept waits for and returns the next connection to the listener. Accept() (Conn, error) // Close closes the listener. // Any blocked Accept operations will be unblocked and return errors. Close() error // Addr returns the listener's network address. Addr() Addr } 只要实现了Listener的三个函数的结构体,都能作为返回参数,以param1=tcp为例子,将会返回TCPListener // TCPListener is a TCP network listener. Clients should typically // use variables of type Listener instead of assuming TCP.</description>
</item>
<item>
<title>ssh连接</title>
<link>http://edcismybrother.github.io/ssh/</link>
<pubDate>Mon, 15 Oct 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/ssh/</guid>
<description>ssh连接服务器 ssh name@host // 如果默认端口不是22,则需要在连接的时候带上参数-P ssh -P 2222 name@host ssh上传文件以及下载文件 // 从本地上传文件 scp localPath/file name@host:/home/src // 意思是将本地路径localPath下的file文件上传到服务器的home/src文件夹下 // 从服务器下载文件 scp name@host:/home/src/file localPath // 意思是将服务器home/src路径下的file文件下载到本地localPath路径下 以上只适合linux系统,如果window想要使用,有两种办法 使用git bash,git bash可以使用ssh以及scp命令 下载pscp,pscp是window下操作的命令,替换scp可以进行相同操作,pscp需要添加到环境变量 pscp下载路径</description>
</item>
<item>
<title>干货达人网址链接</title>
<link>http://edcismybrother.github.io/%E5%B9%B2%E8%B4%A7/</link>
<pubDate>Thu, 11 Oct 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/%E5%B9%B2%E8%B4%A7/</guid>
<description>GitHub上优秀的Go开源项目
awesome优秀框架分享(英文版)
awesome优秀框架分享(中文版)
github上优秀的储存框架</description>
</item>
<item>
<title>golang标准包分析---bytes</title>
<link>http://edcismybrother.github.io/bytes/</link>
<pubDate>Tue, 09 Oct 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/bytes/</guid>
<description>bytes包对外提供的函数 这里将函数分为两类,一类是汇编(这种只需要明白用法就行),一类是使用代码实现的(这种需要好好学习)
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. func Index(s, sep []byte) int {```} 这个函数内部的核心函数是bytealg.Index(),此函数属于汇编类型,用处就是返回首个存在于s中的sep实例的索引,如果不存在返回-1 // Compare returns an integer comparing two byte slices lexicographically. // The result will be 0 if a==b, -1 if a &lt; b, and +1 if a &gt; b. // A nil argument is equivalent to an empty slice.</description>
</item>
<item>
<title>golang标准包分析---archive</title>
<link>http://edcismybrother.github.io/archive/</link>
<pubDate>Sun, 30 Sep 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/archive/</guid>
<description>zip 使用方法 写
// 写到文件中 src,err := os.Create(&quot;/name.zip&quot;) if err != nil{ return } w := zip.NewWriter(src) // 给写入的文件写名字,Create()函数,默认的压缩方式是deflate,需要选择压缩方式可以用CreateHeader() // Store uint16 = 0 // no compression // Deflate uint16 = 8 // DEFLATE compressed f,err := w.Create(&quot;name&quot;) if err != nil{ return } //将内容写入相应的文件中,data是二进制字节流 _,err:=f.write(data) if err != nil { return } // 写完后,需要注意关闭w w.Close() err := w.Close() if err != nil { log.Fatal(err) } 读(常用就是解压缩)
// OpenReader 打开要读取的zip,path:zip文件路径 rc ,err := zip.</description>
</item>
<item>
<title>占位符</title>
<link>http://edcismybrother.github.io/%E5%8D%A0%E4%BD%8D%E7%AC%A6/</link>
<pubDate>Sat, 29 Sep 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/%E5%8D%A0%E4%BD%8D%E7%AC%A6/</guid>
<description>普通占位符 占位符 说明 举例 输出 %v 相应值的默认格式。 Printf(&quot;%v&quot;, people) {zhangsan}, %+v 打印结构体时,会添加字段名 Printf(&quot;%+v&quot;, people) {Name:zhangsan} %#v 相应值的Go语法表示 Printf(&quot;#v&quot;, people) main.Human{Name:&quot;zhangsan&quot;} %T 相应值的类型的Go语法表示 Printf(&quot;%T&quot;, people) main.Human %% 字面上的百分号,并非值的占位符 Printf(&quot;%%&quot;) % 布尔占位符 占位符 说明 举例 输出 %t true 或 false。 Printf(&quot;%t&quot;, true) true 整数占位符 占位符 说明 举例 输出 %b 二进制表示 Printf(&quot;%b&quot;, 5) 101 %c 相应Unicode码点所表示的字符 Printf(&quot;%c&quot;, 0x4E2D) 中 %d 十进制表示 Printf(&quot;%d&quot;, 0x12) 18 %o 八进制表示 Printf(&quot;%d&quot;, 10) 12 %q 单引号围绕的字符字面值,由Go语法安全地转义 Printf(&quot;%q&quot;, 0x4E2D) '中' %x 十六进制表示,字母形式为小写 a-f Printf(&quot;%x&quot;, 13) d %X 十六进制表示,字母形式为大写 A-F Printf(&quot;%x&quot;, 13) D %U Unicode格式:U+1234,等同于 &quot;U+%04X&quot; Printf(&quot;%U&quot;, 0x4E2D) U+4E2D 浮点数和复数的组成部分(实部和虚部) 占位符 说明 举例 输出 %b 无小数部分的,指数为二的幂的科学计数法, 与 strconv.</description>
</item>
<item>
<title>进制学习</title>
<link>http://edcismybrother.github.io/decimal/</link>
<pubDate>Sat, 29 Sep 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/decimal/</guid>
<description>进制对应的英文 name 中文名 含义 举例(以十进制为标准,10的转换) binary 二进制 满2进1 1010 Octal 八进制 满8进1 12 Decimal 十进制 满10进1 10 Hex 十六进制 满16进1 a 进制转换在线工具
golang中进制之间的相互转换 首先看看go自带的包 &ldquo;encoding/hex&rdquo; &ldquo;encoding/binary&rdquo;
重点分析 2、10、16进制之间的相互转换
hex 分析 func Encode(dst, src []byte) int { for i, v := range src { dst[i*2] = hextable[v&gt;&gt;4] dst[i*2+1] = hextable[v&amp;0x0f] } return len(src) * 2 } Encode函数将src目标字节数组,转换成16进制形式的dst字节数组,数组长度翻倍
原理:将原来用一个字节表示的内容,用两个字节来表示,所以返回的dst是src的两倍长度
将原字节右移4位,得到高位内容(ascii码),放在第一个字节,原字节与0000 1111与,得到低位内容(ascii码),放到第二字节
func Decode(dst, src []byte) (int, error) { var i int for i = 0; i &lt; len(src)/2; i++ { a, ok := fromHexChar(src[i*2]) if !</description>
</item>
<item>
<title>dep依赖管理</title>
<link>http://edcismybrother.github.io/dep/</link>
<pubDate>Fri, 28 Sep 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/dep/</guid>
<description> 安装dep go get -u github.com/golang/dep/cmd/dep
dep基本使用 dep init 执行这个命令会将当前目录下所有文件import的第三方工具进行打包
这个建议加上-v ,可以看日志
init是从网络上去下载对应的中间件,包很多的话,下载会非常慢
dep init -gopath 会先去本地找对应的包,没有的话,再去网络上下载
dep ensure -update 依据Gopkg.toml文件的信息获取制定版本的依赖
Gopkg.toml配置小结:
[[constraint]] name = &quot;github.com/panjf2000/ants&quot; version = &quot;=3.6.0&quot; 上述引用为例子:
&quot;3.6.0&quot; 约束使用 3.6.0 - 3.7.0 之间的最新版 &quot;&lt;=3.6.0&quot; 约束使用最高版本为 3.6.0 &quot;=3.6.0&quot; 约束指定为3.6.0 </description>
</item>
<item>
<title>aes加密</title>
<link>http://edcismybrother.github.io/2018/09/25/aes/</link>
<pubDate>Tue, 25 Sep 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/2018/09/25/aes/</guid>
<description>aes加密详解</description>
</item>
<item>
<title>xorm基本操作</title>
<link>http://edcismybrother.github.io/2018/09/25/xorm/</link>
<pubDate>Tue, 25 Sep 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/2018/09/25/xorm/</guid>
<description> 学习链接 </description>
</item>
<item>
<title>简单的tcp实例</title>
<link>http://edcismybrother.github.io/2018/09/24/tcp/</link>
<pubDate>Mon, 24 Sep 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/2018/09/24/tcp/</guid>
<description>tcp服务器 开启对服务器ip以及端口的监听
lis, err := net.Listen(&quot;tcp&quot;, &quot;:6666&quot;) if err != nil { log.Fatalf(&quot;failed to listen:%v&quot;, err) } 用for循环从监听者处取发起拨号的连接
for { conn, err := lis.Accept() if err != nil { log.Fatalf(&quot;failed to accept:%v&quot;, err) continue } sendMessage(conn) time.Sleep(time.Second * 1) } 写两个函数用来收发消息
发消息:将需要发送的消息内容,通过相关的序列化操作,转化成字节流,将字节流通过write函数发送
func send(){ _,err := conn.Write([]byte(str)) if err != nil { log.Fatalf(&quot;failed to write:%v&quot;, err) } } 收消息:通过read函数将字节流读出来,然后通过相关的反序列化操作,得到想要的消息
func recv(){ b := make([]byte,1024) _,err := conn.</description>
</item>
<item>
<title>markdown</title>
<link>http://edcismybrother.github.io/2018/09/24/markdown/</link>
<pubDate>Thu, 20 Sep 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/2018/09/24/markdown/</guid>
<description> 英文学习链接 中文学习链接 </description>
</item>
<item>
<title>submodule</title>
<link>http://edcismybrother.github.io/2018/09/24/submodule/</link>
<pubDate>Thu, 20 Sep 2018 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/2018/09/24/submodule/</guid>
<description> submodule常用命令 新增:在当前库中没有submodule子模块,可以通过 git submodule add remote 添加子模块 删除:
git rm -fr submodule 删除 `./git/config` 文件中的相关submodule 删除 `./git/submodule` 中相关的子模块 新环境中拉取库中的子模块:
初始化`git submodule init` 更新`git submodule update` 拉取所有子模块的最新代码
git submodule foreach &ndash;recursive git pull origin master
git submodule update检出项目的指定版本(HEAD),并不指向一个分支。头指针和分支未绑定,是分离状态。 需要强制绑定
git branch -f master HEAD git checkout master 相关网页
</description>
</item>
<item>
<title>redis学习</title>
<link>http://edcismybrother.github.io/redis/</link>
<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
<guid>http://edcismybrother.github.io/redis/</guid>
<description>redis的四大功能 multi watch discard exec
multi 词条意思是多、多个,这个命令的用途是用来开启事务的,开启事务后,之后执行的cmd命令,都会进入事务队列,并不会马上执行,只有当执行exec后, 队列中的命令才会按顺序进行,执行顺序是先进队列的先执行。如果有一条命令执行失败,那么整个事务都会失败,事务是原子性的。
127.0.0.1:6379&gt; multi //开启事务 OK 127.0.0.1:6379&gt; hset go 1 1 //第一条命令 QUEUED 127.0.0.1:6379&gt; hset go 2 2 //第二条命令 QUEUED 127.0.0.1:6379&gt; exec // 执行队列 1) (integer) 0 2) (integer) 1 discard discard是用来取消事务的,当事务还未执行时,想要取消multi的队列,可以用该命令取消,取消后队列中的所有命令都会取消。
127.0.0.1:6379&gt; multi //开启事务 OK 127.0.0.1:6379&gt; multi //再次开启(失败) (error) ERR MULTI calls can not be nested 127.0.0.1:6379&gt; discard //取消事务 OK exec exec 如上所说,就是用来执行队列的,与multi组合使用
watch 监听事务 ,一般和multi、exec混合使用,watch用来监听某一个键,在事务开始前,如果当前监听的键被其他客户端改动,那么整个事务都会失败。
127.0.0.1:6379&gt; watch go //客户端A监听go OK 127.</description>
</item>
</channel>
</rss>