常见高频题

  • 找出字符串 出现次数最多的字符且有几次(功夫小团子)
def collect(string1):
    dic = {}
    for i in set(string1):
        dic[i] = string1.count(i)
    for k, v in dic.items():
        if v == max(dic.values()):
            print(k,v)

if "__name__" == "__name__":
    string1 = "aaaabbbbbbccccccdd"
    collect(string1)

优化

def collect(string1):
    dic = {}
    max_number = -1
    for i in set(string1):
        dic[i] = string1.count(i)
        if max_number < string1.count(i):
            max_number = string1.count(i)
    for key , value in dic.items():
        if max(dic.value) == value:
            print(key, value)

  • 括号匹配(宇宙)
    def check(string1):
        left = "{(["
        right = "})]"
        dic = dict(zip(left,right))
        list1 = []
        for i in string1:
            if i in left:
                list1.append(i)
            elif i in right:
                # 匹配  / 不匹配
                if list1 and dic[list1[-1]] == i:
                    list1.pop()
                else:
                    return False
        return len(list1) == 0
    string1 = "{}{}{}[]"
    print(check(string1))

二分查找

def binary_search_1(alist,item):
    n = len(alist)
    first = 0
    last = n-1
    while first <= last:
        mid = (first + last) // 2
        if alist[mid] == item:
            return True
        elif alist[mid] < item:
            first = mid + 1
        else:
            last = mid - 1
    return False
  • 最大回文数
class Solution:
    def longestPalindrome(self, s):
        if (len(s) < 2):
            return s
        start = 0  #记录最长回文子串开始的位置
        maxLen = 0 #记录最长回文子串的长度
        for i in range(len(s) - 1):
            for j in range(i,len(s)):#j从i开始,不从i+1开始,s=‘ac’就能选第一个‘a’
                # 法一:截取所有子串,然后在逐个判断是否是回文的
                # 法二(优化):截取所有子串,如果截取的子串小于等于之前遍历过的最大回文串,直接跳过。
                          # 因为截取的子串即使是回文串也不可能是最大的,所以不需要判断
                if (j - i < maxLen):
                    continue
                if self.isPalindrome(s, i, j) and  (maxLen < j - i + 1):
                # maxLen为最大长度时,后面maxLen<j-i+1 就为False,能保证截取最长回文字符串
                    start = i
                    maxLen = j - i + 1
        return s[start:start + maxLen]

    # 判断是否是回文串
    def isPalindrome(self,s,start,end):
        while (start < end) :
            if s[start] != s[end]:
                 return False
            start += 1
            end -= 1
        return True

s =   "ac"
S = Solution()
result = S.longestPalindrome(s)
print(result)
  • 冒泡排序
def my_sort(list1):
    length = len(list1)
    for i in range(length-1):
        for j in range(length-1-i):
            if list1[j] > list1[j+1]:
                list1[j],list1[j+1] = list1[j+1], list1[j]
    print(list1)


list1 = [3,5,2,6,8,35,8,2,6]
my_sort(list1)
  • 判断链表是否带环
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    #
    # 
    # @param head ListNode类 
    # @return bool布尔型
    #
    class Solution:
        def hasCycle(self, head):
            # write code here
            fast = slow = head
            # 如果没有环,则一定会出现下一个节点未空的情况
            # 为什么要判断fast.next也不为空呢?因为下边要去fast.next.next
            while fast is not None and fast.next is not None:
                fast = fast.next.next
                slow = slow.next
                if fast is slow:
                    return True
            return False

    数据库

查找重复姓名的学生

select * from 学生表 where 姓名 in (select 姓名 from 学生表 group by 姓名 having count(姓名) > 2)

查找成绩排名前二的学生

select * from 学生表 order by 成绩 desc limit 2 

<think>好的,我现在需要整理一下关于Redis的常见高频面试,帮助用户准备面试。首先,我得回忆一下自己学过的Redis知识,以及之前看过的面试。可能的问包括基本概念、数据结构、持久化、高可用、应用场景等等。 首先,Redis的基本概念是什么?它是一个内存数据库,支持多种数据结构,比如字符串、哈希、列表、集合、有序集合。还有,Redis是单线程的,但为什么性能还这么高呢?可能是因为它基于内存操作,并且采用了非阻塞I/O多路复用机制。 接下来是数据结构部分。常见的数据结构需要详细说明,比如String、Hash、List、Set、Zset,以及它们的使用场景。比如String适合缓存,Hash适合存储对象,List可以做队列,Zset可以做排行榜。 然后是持久化机制,RDB和AOF的区别。RDB是快照,适合备份,恢复快,但可能丢失数据。AOF记录每次写操作,更安全,但文件大,恢复慢。混合持久化可能是在Redis 4.0之后引入的,结合了两者的优点。 高可用方面,主从复制、哨兵、集群这三种模式需要解释清楚。主从复制实现数据同步,哨兵负责监控和故障转移,集群则提供数据分片和高可用。 缓存相关的问,比如缓存穿透、击穿、雪崩的区别和解决方案。穿透是指查询不存在的数据,可以用布隆过滤器或者缓存空值。击穿是热点key过期导致大量请求到数据库,可以用互斥锁或者永不过期。雪崩是大量key同时过期,可以随机设置过期时间或者集群部署。 事务和管道。Redis的事务是通过MULTI/EXEC命令实现的,但不支持回滚。管道则是将多个命令打包发送,减少网络开销,提升性能。 内存淘汰策略,比如LRU、LFU、随机淘汰等,需要列举不同的策略及其应用场景。 还有可能问到Redis的线程模型,单线程如何处理并发连接,为什么单线程效率高。此外,Redis6.0引入了多线程IO,但执行命令还是单线程的,这点需要说明。 应用场景方面,除了缓存,还有分布式锁、消息队列(使用List或者Stream)、会话存储、计数器、排行榜等。 其他可能的问包括Redis的过期策略(惰性删除和定期删除)、与Memcached的区别、如何实现分布式锁、Redis的集群数据分片方式(哈希槽)等。 需要确保每个问都有简明扼要的回答,并且涵盖高频考点。可能还需要注意一些细节,比如持久化的配置参数,哨兵选举过程,集群的节点通信等。不过用户可能需要的是常见,所以不需要太深入,但重点要突出。 可能还需要检查是否有遗漏的重要问,比如Redis的事务ACID属性,是否支持原子性,或者Redis的并发竞争问如何解决。此外,大key和热key的问,如何处理,也是常见的生产环境问。 总结下来,应该分几个大类来组织问,每个大类下列举几个具体的问和简要答案。这样用户看起来清晰,容易复习。</think>以下是 Redis 常见高频面试及简要解析,助你快速掌握核心知识点: --- ### **一、基础概念** 1. **Redis 是什么?** Redis 是基于内存的键值数据库,支持多种数据结构(String、Hash、List、Set、ZSet等),常用于缓存、消息队列、分布式锁等场景。 2. **Redis 为什么快?** - 内存操作,读写无磁盘 I/O 瓶颈。 - 单线程模型避免上下文切换,配合 I/O 多路复用处理高并发。 - 高效数据结构(如跳表、哈希表)。 --- ### **二、数据结构与应用** 1. **Redis 支持哪些数据结构?应用场景?** - **String**:缓存、计数器(如 `INCR`)。 - **Hash**:存储对象(如用户信息)。 - **List**:消息队列、栈(`LPUSH`/`RPOP`)。 - **Set**:去重、交集(共同好友)。 - **ZSet**:排行榜(按分数排序)。 - **BitMap**:位统计(日活用户)。 - **HyperLogLog**:基数统计(UV)。 - **Stream**:消息流(类似 Kafka)。 2. **ZSet 底层实现?** 使用**跳表(SkipList)** + **哈希表**,跳表支持范围查询,哈希表保证 O(1) 复杂度单值查询。 --- ### **三、持久化** 1. **RDB 和 AOF 的区别?** - **RDB**:定时生成内存快照,文件小、恢复快,但可能丢失最后一次快照后的数据。 - **AOF**:记录每次写命令,数据更安全,但文件大、恢复慢。 - **混合持久化(Redis 4.0+)**:结合两者,AOF 文件包含 RDB 头 + 增量 AOF 命令。 2. **AOF 重写的作用?** 压缩 AOF 文件体积,移除冗余命令(如多次修改同一 key),通过读取内存数据生成新 AOF。 --- ### **四、高可用与集群** 1. **主从复制原理?** 从节点连接主节点后发送 `SYNC` 命令,主节点执行 `BGSAVE` 生成 RDB 文件并发送给从节点,后续通过传播写命令保持同步。 2. **哨兵(Sentinel)机制的作用?** 监控主从节点状态,自动故障转移:当主节点宕机时,选举新主节点并通知客户端。 3. **Redis Cluster 如何分片?** 采用**哈希槽(16384 个槽)**,每个节点负责部分槽。数据按 `CRC16(key) % 16384` 分配到对应槽。 --- ### **五、缓存问** 1. **缓存穿透、击穿、雪崩的区别及解决方案?** - **穿透**:查询不存在的数据。 → 布隆过滤器拦截非法 Key,缓存空值。 - **击穿**:热点 Key 过期后高并发请求压垮数据库。 → 互斥锁(如 `SETNX`)、永不过期 + 异步更新。 - **雪崩**:大量 Key 同时过期。 → 随机过期时间、集群部署、永不过期。 2. **如何保证缓存与数据库一致性?** - 旁路缓存模式(Cache-Aside):先更新库,再删缓存(可能短暂不一致)。 - 延时双删、设置缓存过期时间兜底。 - 最终一致性:通过消息队列异步同步。 --- ### **六、高级特性** 1. **Redis 事务(MULTI/EXEC)的原子性?** 事务中的命令按顺序执行,但非原子(单条命令失败不影响后续执行),不支持回滚。 2. **如何实现分布式锁?** - 使用 `SET key value NX EX` 设置锁(避免死锁)。 - Redlock 算法(多节点部署防止单点故障)。 - 推荐 Redisson 客户端(自动续期、可重入)。 3. **内存淘汰策略有哪些?** - `volatile-lru`/`allkeys-lru`:淘汰最近最少使用的 Key。 - `volatile-lfu`/`allkeys-lfu`:淘汰最不经常使用的 Key。 - `volatile-ttl`:淘汰即将过期的 Key。 - `noeviction`:默认策略,不淘汰,写操作返回错误。 --- ### **七、其他高频** 1. **Redis 单线程为什么高效?** 纯内存操作 + 非阻塞 I/O 多路复用(epoll)处理高并发,避免线程切换开销。 2. **Pipeline 的作用?** 批量发送命令,减少网络往返次数,提升批量操作性能(但非原子性)。 3. **大 Key 和热 Key 问如何解决?** - **大 Key**:拆分(如 Hash 分多个 Key)、异步删除(`UNLINK`)。 - **热 Key**:多级缓存、本地缓存、Key 打散分布。 --- 掌握以上问后,可进一步结合实际场景和源码深入理解,面试时结合项目经验回答更佳!
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值