ARTS #63

Algorithm

142. 环形链表 II
使用快慢指针可以推导出相遇点到入环点的距离等于起始点到入环点的距离

func detectCycle(head *ListNode) *ListNode {
    fast := head
    slow := head
    for fast != nil {
        slow = slow.Next
        if fast.Next == nil {
            return nil
        }
        fast = fast.Next.Next
        if slow == fast {
            result := head
            for {
                if slow == result {
                    return result
                }else{
                    slow = slow.Next
                    result = result.Next
                }
            }
        }
    }
    return nil
}

Review

Organizing projects and defining names in Go
本文介绍了作者在他们项目实践中遵循的一些编码规范,包括:

  1. 如何组织一个library项目:
  • 遵循单一职责规范
  • 必要的时候声明好interface并在sub_package中进行相关implement
  • 包名命名尽量简洁准确
  1. 如何组织一个application项目:
├── README.md
├── go.mod
├── go.sum
├── cmd
│   ├── api
│   │   └── main.go
│   └── appctl
│       └── main.go
├── config
│   ├── config.go
├── book
│   ├── book.go
│   ├── service.go
│   ├── service_test.go
│   ├── mock
│   │   ├── service.go
│   │   ├── repository.go
│   ├── postgres
│   │   ├── book_storage.go
│   │   ├── book_storage_test.go
├── internal
│   ├── http
│       ├── gin
│        ├── handler.go
|        ├── book.go
│        ├── book_test.go
│   ├── event
│   │   ├── event.go
│   │   └── event_test.go
│   │   │── kafka
│   │       ├── event.go
│   │       ├── event_test.go
  1. 包、函数、变量命名:
  • 包名:尽量短、清晰表达包职责(遵循单一职责)
  • 变量:驼峰命名、简单清晰
  • 函数:避免和包名重复表达

TIP

Go设计模式--命令模式

"本文使用的完整可运行源码
去公众号「网管叨bi叨」发送【设计模式】即可领取"
// 命令接收者,负责逻辑的执行
type CPU struct{}

func (CPU) ADoSomething(param int) {
 fmt.Printf("a do something with param %v\n", param)
}
func (CPU) BDoSomething(param1 string, param2 int) {
 fmt.Printf("b do something with params %v and %v \n", param1, param2)
}
func (CPU) CDoSomething() {
 fmt.Println("c do something with no params")
}

// 接口中仅声明一个执行命令的方法 Execute()
type Command interface {
 Execute()
}

// 命令对象持有一个指向接收者的引用,以及请求中的所有参数,
type ACommand struct {
 cpu *CPU
 param int
}
// 命令不会进行逻辑处理,调用Execute方法会将发送者的请求委派给接收者对象。 
func (a ACommand) Execute() {
 a.cpu.ADoSomething(a.param)
 a.cpu.CDoSomething()// 可以执行多个接收者的操作完成命令宏
}

func NewACommand(cpu *CPU, param int) Command {
 return ACommand{cpu, param}
}

"本文使用的完整可运行源码
去公众号「网管叨bi叨」发送【设计模式】即可领取"
type BCommand struct {
 state bool // Command 里可以添加些状态用作逻辑判断
 cpu *CPU
 param1 string
 param2 int
}

func (b BCommand) Execute() {
 if b.state {
  return
 }
 b.cpu.BDoSomething(b.param1, b.param2)
 b.state = true
 b.cpu.CDoSomething()
}

func NewBCommand(cpu *CPU, param1 string, param2 int) Command {
 return BCommand{false,cpu, param1, param2}
}

type PS5 struct {
 commands map[string]Command
}

// SetCommand方法来将 Command 指令设定给PS5。
func (p *PS5) SetCommand(name string, command Command) {
 p.commands[name] = command
}
// DoCommand方法选择要执行的命令
func (p *PS5) DoCommand(name string) {
 p.commands[name].Execute()
}

func main() {
 cpu := CPU{}
    // main方法充当客户端,创建并配置具体命令对象, 完成命令与执行操作的接收者的关联。
 ps5 := PS5{make(map[string]Command)}
 ps5.SetCommand("a", NewACommand(&cpu, 1))
 ps5.SetCommand("b", NewBCommand(&cpu, "hello", 2))
 ps5.DoCommand("a")
 ps5.DoCommand("b")
}

Share

学习mysql 45讲

31 | 误删数据后除了跑路, 还能怎么办?

误删行

用Flashback工具通过闪回把数据恢复回来。Flashback恢复数据的原理, 是修改binlog的内容, 拿回原库重放。 而能够使用这个方案的前提是, 需要确保binlog_format=row和 binlog_row_image=FULL。
具体恢复数据时, 对单个事务做如下处理:

  1. 对于insert语句, 对应的binlog event类型是Write_rows event, 把它改成Delete_rows event即可;
  2. 同理, 对于delete语句, 也是将Delete_rows event改为Write_rows event;
  3. 而如果是Update_rows的话, binlog里面记录了数据行修改前和修改后的值, 对调这两行的位置即可。

误删库/表

这种情况下, 要想恢复数据, 就需要使用全量备份, 加增量日志的方式了。 这个方案要求线上有定期的全量备份, 并且实时备份binlog。
在这两个条件都具备的情况下, 假如有人中午12点误删了一个库, 恢复数据的流程如下:

  1. 取最近一次全量备份, 假设这个库是一天一备, 上次备份是当天0点;
  2. 用备份恢复出一个临时库;
  3. 从日志备份里面, 取出凌晨0点之后的日志;
  4. 把这些日志, 除了误删除数据的语句外, 全部应用到临时库。

延迟复制备库

延迟复制的备库是一种特殊的备库, 通过 CHANGE MASTER TO MASTER_DELAY = N命令,可以指定这个备库持续保持跟主库有N秒的延迟。
比如你把N设置为3600, 这就代表了如果主库上有数据被误删了, 并且在1小时内发现了这个误操作命令, 这个命令就还没有在这个延迟复制的备库执行。 这时候到这个备库上执行stop slave, 再通过之前介绍的方法, 跳过误操作命令, 就可以恢复出需要的数据。

rm删除数据

只要不是恶意
地把整个集群删除, 而只是删掉了其中某一个节点的数据的话, HA系统就会开始工作, 选出一个新的主库, 从而保证整个集群的正常工作。这时, 你要做的就是在这个节点上把数据恢复回来, 再接入整个集群。

32 | 为什么还有kill不掉的语句?

收到kill以后, 线程做什么?

实现上, 当用户执行kill query thread_id_B时, MySQL里处理kill命令的线程做了两件事:

  1. 把session B的运行状态改成THD::KILL_QUERY(将变量killed赋值为THD::KILL_QUERY);
  2. 给session B的执行线程发一个信号。

kill无法生效的情况

  1. kill无效的第一类情况, 即: 线程没有执行到判断线程状态的逻辑。
  2. 另一类情况是, 终止逻辑耗时较长。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容