ARTS #72

Algorithm

221. 最大正方形

func maximalSquare(matrix [][]byte) (result int) {
    m := len(matrix)
    n := len(matrix[0])
    results := make([][]int, m)
    maxSize := 0
    for i := 0; i < m; i++ {
        results[i] = make([]int, n)
        for j := 0; j < n; j++ {
            if matrix[i][j] == '1' {
                results[i][j] = 1
                var temp int
                if i == 0 || j == 0 {
                    temp = 1
                } else {
                    temp = min(min(results[i-1][j-1], results[i][j-1]), results[i-1][j]) + 1
                }
                results[i][j] = temp
                if temp > maxSize {
                    maxSize = temp
                }
            } else {
                results[i][j] = 0
            }
        }
    }
    result = maxSize * maxSize
    return
}

func min(x, y int) int {
    if x <= y {
        return x
    }
    return y
}

Review

NA

TIP

这周在工作过程接触到公司redis的热承载功能,这里记录下。

应用场景

业务上如果有热点key的问题,可以通过开始热承载来解决。比如现在有个功能是通过直播间ID获取当前直播间正在售卖的商品列表,对应到代码层面的设计就是key是room_id,value是product_id list。这种设计会导致头部主播开播过程如果看播的观众特别多,会有大量的请求(10万qps以上)去同一个redis分片读取同一个room_id key进而导致这个redis分片负载较高影响业务,这就是一个典型的业务热点场景。

原理

目前公司内部redis实现架构是redis client -> redis proxy -> redis server,而热承载开启之后会在client和proxy上维护一个localcache,如果请求命中了localcache就直接返回对应的值,从而减少redis server的压力。当然这里只是大体设计,具体的技术细节不能透漏太多。

优点

业务遇到热点场景不需要自己在业务端实现一套localcache了,直接开启热承载就可以了。

缺点

  1. 有缓存必然就涉及到一致性问题,不可避免。
  2. 不能定制化localcache,只能单纯地使用原始的kv值。

Share

学习“redis设计与实现”

压缩列表

Ziplist 是由一系列特殊编码的内存块构成的列表,一个 ziplist 可以包含多个节点(entry),每个节点可以保存一个长度受限的字符数组(不以 \0 结尾的 char 数组)或者整数。

ziplist 的构成

image.png

节点的构成

image.png
pre_entry_length

pre_entry_length 记录了前一个节点的长度,通过这个值,可以进行指针计算,从而跳转到上一个节点。

encoding 和 length

encoding 域的长度为两个 bit ,它的值可以是 00 、01 、10 和 11:
• 00 、01 和 10 表示 content 部分保存着字符数组。
• 11 表示 content 部分保存着整数。

content

content 部分保存着节点的内容,它的类型和长度由 encoding 和 length 决定

将节点添加到末端

将新节点添加到 ziplist 的末端需要执行以下三个步骤:

  1. 记录到达 ziplist 末端所需的偏移量(因为之后的内存重分配可能会改变 ziplist 的地址,因此记录偏移量而不是保存指针)
  2. 根据新节点要保存的值,计算出编码这个值所需的空间大小,以及编码它前一个节点的长度所需的空间大小,然后对 ziplist 进行内存重分配。
  3. 设置新节点的各项属性:pre_entry_length 、encoding 、length 和 content 。
  4. 更新 ziplist 的各项属性,比如记录空间占用的 zlbytes ,到达表尾节点的偏移量 zltail,以及记录节点数量的 zllen 。

将节点添加到某个/某些节点的前面

  1. 记录到达 ziplist 末端所需的偏移量(因为之后的内存重分配可能会改变 ziplist 的地址,因此记录偏移量而不是保存指针)
  2. 根据新节点要保存的值,计算出编码这个值所需的空间大小,以及编码它前一个节点的长度所需的空间大小,然后对 ziplist 进行内存重分配。
  3. 设置新节点的各项属性:pre_entry_length 、encoding 、length 和 content 。
  4. 更新 ziplist 的各项属性,比如记录空间占用的 zlbytes ,到达表尾节点的偏移量 zltail,以及记录节点数量的 zllen 。
  5. 将 new 节点的长度编码进 next 节点的 pre_entry_length 域里。这里会出现三种可能:
  • next 的 pre_entry_length 域的长度正好能够编码 new 的长度(都是 1 字节或者都是 5字节)
  • next 的 pre_entry_length 只有 1 字节长,但编码 new 的长度需要 5 字节
  • next 的 pre_entry_length 有 5 字节长,但编码 new 的长度只需要 1 字节

对于情况 1 和 3 ,程序直接更新 next 的 pre_entry_length 域。
如果是第二种情况,那么程序必须对 ziplist 进行内存重分配,从而扩展 next 的空间。然而,因为 next 的空间长度改变了,所以程序又必须检查 next 的后继节点——next+1 ,看它的pre_entry_length 能否编码 next 的新长度,如果不能的话,程序又需要继续对 next+1 进行扩容。程序必须沿着路径一个个检查后续的节点是否满足新长度的编码要求,直到遇到一个能满足要求的节点(如果有一个能满足,那么这个节点之后的其他节点也满足),或者到达 ziplist 的末端 zlend 为止,这种检查操作的复杂度为O(N2) 。

删除节点

  1. 定位目标节点,并计算节点的空间长度 target-size
  2. 进行内存移位,覆盖 target 原本的数据,然后通过内存重分配,收缩多余空间
  3. 检查 next 、next+1 等后续节点能否满足新前驱节点的编码。和添加操作一样,删除操作也可能会引起连锁更新。

遍历

可以对 ziplist 进行从前向后的遍历,或者从后先前的遍历。
当进行从前向后的遍历时,程序从指向节点 e1 的指针 p 开始,计算节点 e1 的长度(e1-size),然后将 p 加上 e1-size ,就将指针后移到了下一个节点 e2 。
当进行从后往前遍历的时候,程序从指向节点 eN 的指针 p 出发,取出 eN 的 pre_entry_length值,然后用 p 减去 pre_entry_length ,这就将指针移动到了前一个节点 eN-1。

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

推荐阅读更多精彩内容