redis2-数据类型|常用命令|应用场景 r囧r小猫 2022-05-14 11:40 196阅读 0赞 ### 文章目录 ### * * 基础数据类型: * redis命令 * * 高级结构 * redis高级命令 * 面试题 * * * (1)使用过==Redis分布式锁==么,它是什么回事? * (2)使用过Redis做异步队列么,你是怎么用的? * (3)如果有大量的key需要设置同一时间过期,一般需要注意什么? * (4)Redis如何做持久化的? * (5)Pipeline有什么好处,为什么要用pipeline? * (6)Redis的同步机制了解么? * (7)是否使用过Redis集群,集群的原理是什么? * 内存CPU问题 * * redis内存满了怎么办 * CPU过高怎么办 * redis性能优化 * redis占用资源监控工具——redis-monitor ## 基础数据类型: ## [菜鸟教程链接 全面][Link 1] 1. String类型 set name zhaojianyu # 如果已经存在则会覆盖 setnx name aaa # 如果已经存在,不会覆盖返回0 set email 111@qq.com setrange email 3 163.com # 从第四位开始替换,将qq.com替换为163.com # 设置为0时替换整个字符串 incr key 执行+1 `incrby key 3` 加3 `incrby key -2` 减2 可应用于计数器(浏览次数,全局唯一id) 1. Hash类型(最常用) `hset/hmset` https://www.runoob.com/redis/redis-hashes.html 2. [list类型 (消息队列)][list_] * LPUSH key value1 \[value2\] 将一个或多个值插入到列表头部 * LRANGE key start stop 获取列表指定范围内的元素 * LTRIM key start stop 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。 1. 集合Set(抽奖活动) # 参加抽奖活动 sadd key { userId} # 获取所有抽奖用户,大轮盘转起来 smembers key # 抽取count名中奖者,并从抽奖活动中移除 spop key count # 抽取count名中奖者,不从抽奖活动中移除 srandmember key count 1. 有序集合ZSet (排行榜) skiplist [跳表][Link 2] ## redis命令 ## 1. `exists key` 是否存在key 2. `del key1 key2 key3`删除 3. `rename key1 key2`重命名 4. `type key` 查看类型 5. 默认16个数据库,默认使用0号数据库`select 5`切换数据库 6. `move key 1`移动key值 ### 高级结构 ### 1. **HyperLogLog基数统计** 2.8.9在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。[菜鸟教程之hyperLogLog][hyperLogLog] 统计在线用户数||||统计用户每天搜索不同词条的个数 2. **Geo**3.2 将指定的地理空间位置(纬度、经度、名称)添加到指定的key中。 返回两个给定位置之间的距离。 支持存储地理位置信息用来实现诸如摇一摇,附近位置这类依赖于地理位置信息的功能。 3. **Pub/Sub发布订阅** . [菜鸟教程][Link 3] 4. Redis Module扩展模块4.0 5. BloomFilter 6. RedisSearch 7. Redis-ML ### redis高级命令 ### 1. keys命令 keys * # 查询所有key列表 keys li* # 查询所有以li开头的所有key列表 keys算法是遍历算法,复杂度是**O(n)** redis的单线程的。**keys指令会导致线程阻塞一段时间**,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,**但是整体所花费的时间会比直接用keys指令长**。 `info`可以看到所有库的key数量 \# 查看数据库信息 `dbsize`则是当前库key的数量 1. `scan`命令 scan cursor \[match pattern\] \[count count\] 复杂度虽然也是 O(n),但是它是通过游标分步进行的,不会阻塞线程 提供 count 参数,不是结果数量,是Redis单次遍历字典槽位数量(约等于) 同 keys 一样,它也提供模式匹配功能; 服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数; 返回的结果可能会有重复,需要客户端去重复,这点非常重要; 单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零 1. 关于有效期的命令 setex color 10 red # 设置color有效期为10秒 expire name 5 # 给key为name的设置5秒有效期 ttl name # 查看key为name的剩余有效期 persist name #取消过期时间 1. 事务 常用命令`MULTI、EXEC、DISCARD、WATCH` `multi`开启事务 `exec`提交事务 `discard`回滚 ## 面试题 ## #### (1)使用过Redis分布式锁么,它是什么回事? #### 先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。 然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?这个锁就永远得不到释放了。 回答:我记得set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的! #### (2)使用过Redis做异步队列么,你是怎么用的? #### 一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。如果对方追问可不可以不用sleep呢?list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。如果对方追问能不能生产一次消费多次呢?使用pub/sub主题订阅者模式,可以实现1:N的消息队列。如果对方追问pub/sub有什么缺点?在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。如果对方追问redis如何实现延时队列?我估计现在你很想把面试官一棒打死如果你手上有一根棒球棍的话,怎么问的这么详细。但是你很克制,然后神态自若的回答道:使用sortedset,拿时间戳作为score,消息内容作为key调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理。 #### (3)如果有大量的key需要设置同一时间过期,一般需要注意什么? #### 如果大量的key过期时间设置的过于集中,到过期的那个时间点,redis可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一些。 #### (4)Redis如何做持久化的? #### **RDB持久化(默认)** 周期性写入磁盘一次 **AOF持久化** bgsave做镜像全量持久化,aof做增量持久化。因为bgsave会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要aof来配合使用。 在redis实例重启时,优先使用aof来恢复内存的状态,如果没有aof日志,就会使用rdb文件来恢复。 如果再问aof文件过大恢复时间过长怎么办? 你告诉面试官,**Redis会定期做aof重写,压缩aof文件日志大小**。如果面试官不够满意,再拿出杀手锏答案, Redis4.0之后有了混合持久化的功能,**将bgsave的全量和aof的增量做了融合处理**,这样既保证了恢复的效率又兼顾了数据的安全性。这个功能甚至很多面试官都不知道,他们肯定会对你刮目相看。 如果对方追问那如果突然机器掉电会怎样? 取决于aof日志sync属性的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s的数据。 如果对方追问bgsave的原理是什么? 你给出两个词汇就可以了,fork和cow。fork是指redis通过创建子进程来进行bgsave操作,cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。 1、aof文件比rdb更新频率高,优先使用aof还原数据。 2、aof比rdb更安全也更大 3、rdb性能比aof好 4、如果两个都配了优先加载AOF #### (5)Pipeline有什么好处,为什么要用pipeline? #### 可以将多次IO往返的时间缩减为一次,前提是pipeline执行的指令之间没有因果相关性。使用redis-benchmark进行压测的时候可以发现影响redis的QPS峰值的一个重要因素是pipeline批次指令的数目。 #### (6)Redis的同步机制了解么? #### Redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将rdb文件全量同步到复制节点,复制节点接受完成后将rdb镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。 #### (7)是否使用过Redis集群,集群的原理是什么? #### Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。 # 内存CPU问题 # 优点: 1. 采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求; 2. 避免线程切换而消耗CPU 缺点: 3. 无法发挥多核CPU性能,不过可以通过在单机开多个Redis实例来完善 ## redis内存满了怎么办 ## 增加内存 使用内存淘汰策略 搭建redis集群 ## CPU过高怎么办 ## 解决: 1. 连接数过多,通过`redis-cli info | grep connected_clients`查看当前连接 关闭僵尸连接; redis-cli登录后,client list查看所有客户端连接,`client kill ${ip}:${port}`关闭连接; 2. 修改最大连接数`maxclients: 10000`,默认10000; 3. 修改redis timeout参数: 修改配置文件中的timeout 设置redis的keepalive时间。客户端断连的包发出去后,redis server没有接受到,则会出现redis server以为连接正常的情况。因此需要在redis server 启动超时设置,如果在一定的时间内,客户端没有消息过来,则redis server主动断开连接。 4. 修改redis进程的文件数限制: echo -n “Max open files 3000:3000” > /proc/PID/limits 5. 修改系统参数的最大文件数限制: /etc/security/limits.conf; redis服务器默认设置的最大连接数maxclients是10000,但是受服务器最大文件数影响,服务器默认最大文件数是1024,所以redis最大连接也为1024-32=992; 解决办法 6. **慢查询** ,因为redis是单线程,如果有慢查询的话,会阻塞住之后的操作,通过redis日志查 value值过大:如果是纯文本,可以考虑换种存储方式,如果是对象,可以考虑用hash; 7. aof重写/rdb fork发生?瞬间会堵一下Redis服务器 ## redis性能优化 ## Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化。 如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。 为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内。 尽量避免在压力较大的主库上增加从库。 为了Master的稳定性,主从复制不要用图状结构,用单向链表结构更稳定,即主从关系为:Master<–Slave1<–Slave2<–Slave3…,这样的结构也方便解决单点故障问题,实现Slave对Master的替换,也即,如果Master挂了,可以立马启用Slave1做Master,其他不变 使用Redis负载监控工具:redis-monitor,它是一个Web可视化的 redis 监控程序 redis分库,这样方便于管理与维护。 ## redis占用资源监控工具——redis-monitor ## [Link 1]: https://www.runoob.com/redis/redis-tutorial.html [list_]: https://www.runoob.com/redis/redis-lists.html [Link 2]: https://syt-honey.github.io/2019/03/23/17-%E8%B7%B3%E8%A1%A8%EF%BC%9A%E4%B8%BA%E4%BB%80%E4%B9%88Redis%E4%B8%80%E5%AE%9A%E8%A6%81%E7%94%A8%E8%B7%B3%E8%A1%A8%E6%9D%A5%E5%AE%9E%E7%8E%B0%E6%9C%89%E5%BA%8F%E9%9B%86%E5%90%88%EF%BC%9F/ [hyperLogLog]: https://www.runoob.com/redis/redis-hyperloglog.html [Link 3]: https://www.runoob.com/redis/redis-pub-sub.html
还没有评论,来说两句吧...