在分析redis集群中大Key的时候,通常都采用分析rdb文件的方式;但是这种方式需要在每一台redis服务器上部署分析程序及分析脚本,而像salt之类的工具运维没有开放给我们使用,一台一台部署不好管理。正好我们的总redis规模不大,大概在200个集群左右,考虑到cluster集群,需要分析的redis实例数在300左右,所以就想着能不能通过scan的方式来进行。

通过scan命令扫描从库,将集群中key深度大于指定值的key扫描出来,将这些 key 放在一个slice中,取 top N,这就需要对 slice中的 key按照深度进行排序。300个实例说多不多,说少不少,排序算法的性能还是很重要的。快速排序针对小数据量排序性能很好,正好mysql在使用sort buffer进行排序时采用的是快速排序,这里就用go实现来复习一下快速排序算法。

func sortBigKeySlice(bigKeySlice []*bigKeyInstance) {
if len(bigKeySlice) < 2 {
return
}
sortBigKey(bigKeySlice, 0, len(bigKeySlice))
} //使用递归实现
func sortBigKey(bigKeySlice []*bigKeyInstance, low, high int) {
if low >= high {
return
}
p := partition(bigKeySlice, low, high)
sortBigKey(bigKeySlice, low, p)
sortBigKey(bigKeySlice, p + 1, high)
}
//普通快速排序,对于普通快速排序,将第一个元素作为基准,小于该元素的放在左边,大于等于该元素的放在右边
func partition(bigKeySlice []*bigKeyInstance, low, high int) int{
//直接将第一个元素作为分隔值
pivotIns := bigKeySlice[low]
//当前第一个元素点位作为标记点
pivotPos := low //去除第一个分割值,遍历元素,如果元素比分割值小,将标记点右移一位,交换元素的值,大于等于则继续比较下一个元素
for i := low + 1; i < high; i++ {
if bigKeySlice[i].size < pivotIns.size {
pivotPos += 1
bigKeySlice[pivotPos], bigKeySlice[i] = bigKeySlice[i], bigKeySlice[pivotPos]
} else {
continue
}
}
//不要忘记最后的互换,将分隔值与标记点元素互换
bigKeySlice[low], bigKeySlice[pivotPos] = bigKeySlice[pivotPos], bigKeySlice[low]
return pivotPos
}

  

普通快速排序默认左边的第一个元素作为基准数,对于渐进有序的数组来说,这就导致小于基准的数会相当少,而大于等于基准的数相当多,造成分区不平衡的问题,普通排序就会退化,严重的将退化成O(n^2)。所以对其改进:不再默认选择第一个数,而是随机选一个数作为基准,这样的快排称为随机普通快排。

//随机普通快速排序,不使用第一个元素作为基准,而是使用一个随机元素作为基准
func partition(bigKeySlice []*bigKeyInstance, low, high int) int {
//取slice中的一个随机元素作为分割点,而不是第一个元素开始分割
rand_low := low + rand.Intn(high - low)
bigKeySlice[low], bigKeySlice[rand_low] = bigKeySlice[rand_low], bigKeySlice[low]
pivotPos := low
for i := low + 1; i < high; i++ {
if bigKeySlice[i].size < bigKeySlice[low].size {
pivotPos += 1
bigKeySlice[pivotPos], bigKeySlice[i] = bigKeySlice[i], bigKeySlice[pivotPos]
} else {
continue
}
}
bigKeySlice[low], bigKeySlice[pivotPos] = bigKeySlice[pivotPos], bigKeySlice[low]
return pivotPos
}

  

对于含有大量重复元素的数组,则对于与基准数相同的数,要么分到了左边,要么分到了右边,同样会造成分治不平衡的问题,造成性能退化。这时,采用双路排序或三路排序进行改进。

双路排序 & 三路排序待续....

快速排序算法 - go实现的更多相关文章

  1. 快速排序算法 java 实现

    快速排序算法 java 实现 快速排序算法Java实现 白话经典算法系列之六 快速排序 快速搞定 各种排序算法的分析及java实现 算法概念 快速排序是C.R.A.Hoare于1962年提出的一种划分 ...

  2. C# 集合扩展快速排序算法

    /// <summary> /// 对集合进行排序,如 /// List<Person> users=new List<Person>(){.......} /// ...

  3. PHP描述冒泡排序和快速排序算法

    使用PHP描述冒泡排序和快速排序算法,对象可以是一个数组.使用PHP描述顺序查找和二分查找(也叫做折半查找)算法,顺序查找必须考虑效率,对象可以是一个有序数组.写一个二维数组排序算法函数,能够具有通用 ...

  4. 快速排序算法(Java)

    快速排序算法的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另外一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序. class Parti ...

  5. 快速排序算法-C语言实现

    注:本篇内容为翻译,之所以选择这篇进行翻译原因是该文章含有动画,能够更加直观地展示快速排序.同时,可以仔细看一下代码,代码中把结构化的思想给予了更加充分地表现.按照功能进行模块划分的思想得到了彻底地贯 ...

  6. C#快速排序算法基础入门篇

    相信算法对于许多开发人员来说都是一大难点,之所以难,就像设计模式一样,许多人在阅读之后,没有很好地理解,也不愿意动手上机操作,只停留在理论的学习上面,随着时间推移就慢慢淡忘. 有些东西,你可以发明创造 ...

  7. 快速排序算法 Quick sort

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4046189.html 首先随机选择一个轴,并调整数组内各个数字,使得比轴值大的数在轴的右边, ...

  8. PHP实现快速排序算法

    快速排序(Quick Sort)是对冒泡排序的一种改进,属不稳定排序算法,由东尼·霍尔在1962年提出.快速排序基本步骤:从数列中挑出一个元素(一般称为称为“基准”),通过一趟排序将要排序的数据分割成 ...

  9. Java快速排序算法

    快速排序算法思想: 快速排序(Quicksort)是对冒泡排序的一种改进. 快速排序由C. A. R. Hoare在1962年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一 ...

  10. 排序系列 之 快速排序算法 —— Java实现

    基本思想: 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变 ...

随机推荐

  1. sqlserver 中,如何将getdate()时间的时分秒固定为00:00:00或者忽略不要

    在使用getdate()时,时间会实时刷新,那么我们就要再查询的时候就需要精确到毫秒后三位,非常难受,那么为了解决这个问题我们可以通过以下几种方法进行固定或者去掉毫秒 1.将毫秒固定为00:00:00 ...

  2. Kubernetes 使用kubeadm创建集群

    镜像下载.域名解析.时间同步请点击 阿里巴巴开源镜像站 实践环境 CentOS-7-x86_64-DVD-1810 Docker 19.03.9 Kubernetes version: v1.20.5 ...

  3. 【文件系统】dumpe2fs命令

    dumpe2fs - dump ext2/ext3/ext4 filesystem information dumpe2fs prints the super block and blocks gro ...

  4. Nacos配置中心集群原理及源码分析

    Nacos作为配置中心,必然需要保证服务节点的高可用性,那么Nacos是如何实现集群的呢? 下面这个图,表示Nacos集群的部署图. Nacos集群工作原理 Nacos作为配置中心的集群结构中,是一种 ...

  5. lombok的@builder 不能新建DO对象 Lombok存在的一些问题

    1. 实体类加上 lombok的@builder之后  就不能新建对象了,,,构造函数被覆盖了? 加上两个标签之后解决 2.Lombok存在的一些问题 lombok问题 @Builder和@NoArg ...

  6. nginx搭建简单直播服务器

    1.下载模块(nginx-rtmp-module) 1 cd /data/nginx 2 yum install git3 git clone https://github.com/arut/ngin ...

  7. vulnhub靶机Tr0ll:1渗透笔记

    Tr0ll:1渗透笔记 靶场下载地址:https://www.vulnhub.com/entry/tr0ll-1,100/ kali ip:192.168.20.128 靶机和kali位于同一网段 信 ...

  8. 路径规划—BUG算法

  9. 单片机ram和rom的区别

    单片机运行时需要调用某个程序/函数/固定数据时就需要读取ROM,然后在RAM中执行这些程序/函数的功能,所产生的临时数据也都存在RAM内,断电后这些临时数据就丢失了.ROM:(Read Only Me ...

  10. 【动态系统的建模与分析】8_频率响应_详细数学推导 G(jw)_滤波器