Loading... ~~正好是用 Markdown 写的,能直接复制过来真的太爽了!~~ # Basic Commands ~~~ exists <key> #判断 key 是否存在,存在返回 1,不存在返回 0 ~~~ ~~~ del <key> #删除指定 key ~~~ ~~~ ttl <key> #查询记录所剩余的生命周期 ~~~ ``` type <key> #查询 key 对应的值的类型 ``` ``` rename <keyOldName> <newName> #重命名 key ``` ``` randomkey #随机返回一个 key ``` ~~~ dbsize #查询数据库占用大小 ~~~ ~~~ select <number> #切换数据库 ~~~ ~~~ flushdb #清空当前数据库 ~~~ ~~~ flushall #清空所有数据库 ~~~ # String(字符串) ~~~ set <key> <value> #通过 KV 添加新记录 ~~~ ~~~ get <key> #根据 key 获取数据 ~~~ ~~~ strlen <key> #根据 key 返回数据的长度 ~~~ ~~~ append <key> <content> #根据 key 追加新数据 ~~~ ~~~ incr/decr <key> #若数据为数字,则自增自减 ~~~ ~~~ incrby/decrby <key> <number> #若数据为数字,则根据自定义的步长增/减 ~~~ ~~~ getrange <key> <start> <end> #根据 key 和起始结束位置截取字符串(闭区间)[PS:-1 为最后] ~~~ ~~~ setrange <key> <start> <content> #根据 key 从指定位置通过自定义的 content 修改字符串内容 ~~~ ~~~ setex <key> <seconds> <value> #添加指定秒数后过期的记录 ~~~ ~~~ setnx <key> <value> #若不存在相同的 key,才会添加新记录 ~~~ ~~~ mset <key1> <value1> <key2> <value2>... #批量添加记录 ~~~ ~~~ msetnx <key1> <value1> <key2> <value2>... #【原子性!】批量添加记录,若该行内有任一 key 存在,则整行语句不会生效 ~~~ ~~~ mget <key1> <key2>... #批量查询记录 ~~~ ~~~ set user:1 {name:sb,age:12} || mset user:1:name sb user:1:age 12 #对象添加示例 ~~~ ~~~ getset <key> <value> #先根据 key 获取 value 并输出,再添加记录 ~~~ # List(列表) ~~~ lpush/rpush <name> <element> #添加一个元素到指定列表的头部/尾部 ~~~ ~~~ lrange <name> <start> <end> #从头部开始获取列表指定区间的所有值[全部则为-1] ~~~ ~~~ lpop/rpop <name> #移除列表头部/尾部的元素 ~~~ ~~~ lindex <name> <index> #获取列表指定下标的元素 ~~~ ~~~ llen <name> #获取列表长度 ~~~ ~~~ lrem <name> <count> <element> #移除列表内指定数量的指定元素(后添加的先被删) ~~~ ~~~ ltrim <name> <start> <end> #截取保留列表指定区间的元素并修改原列表 ~~~ ~~~ rpoplpush <oldlist> <newlist> #移除旧列表的最后一个元素,添加到新列表中 ~~~ ~~~ lset <name> <index> <element> #修改列表指定下标的元素为新值 ~~~ ~~~ linsert <name> before|after <element> <insertElement> #在列表指定元素的前或后插入新元素 ~~~ # Set(集合) ~~~ sadd <name> <value> #添加元素到 Set ~~~ ~~~ smembers <name> #获取 Set 所有元素 ~~~ ~~~ sismsmber <name> <value> #判断一个 Set 内是否包含某元素 ~~~ ~~~ scard <name> #获取 Set 的长度 ~~~ ~~~ srem <name> <value> #删除 Set 内的指定元素 ~~~ ~~~ srandmember <name> <count> #随机抽取 Set 内的任意个元素 ~~~ ~~~ spop <name> #随机删除 Set 的一个元素 ~~~ ~~~ smove <oldSet> <newSet> <member> #移动一个 Set 的指定元素到新的 Set 中 ~~~ ~~~ sdiff <Set1> <Set2> #获取两个 Set 的差集(不同的值) ~~~ ~~~ sinter <Set1> <Set2> #获取两个 Set 的交集(都有的值) ~~~ ~~~ sunion <Set1> <Set2> #获取两个 Set 的并集(合并后) ~~~ # Hash(哈希) ~~~ hset <name> <key> <value> #往 Hash 添加一个 KV 记录 ~~~ ~~~ hsetnx <name> <key> <value> #若 Hash 内此 Key 不存在,则添加该 KV 记录 ~~~ ~~~ hget <name> <key> #获取 Hash 内的一个 Key 的值 ~~~ ~~~ hmset <name> <key1> <value1> <key2> <value2>... #Hash 批量添加记录 ~~~ ~~~ hmget <name> <key1> <key2>... #Hash 根据 Key 批量获取记录 ~~~ ~~~ hgetall <name> #获取 Hash 内所有 Key 和 Value ~~~ ~~~ hdel <name> <key> #删除 Hash 内指定 Key 的记录 ~~~ ~~~ hlen <name> #获取 Hash 字段的数量 ~~~ ~~~ hexists <name> <key> #判断 Hash 内是否存在对应 Key ~~~ ~~~ hkeys <name> #获取 Hash 内所有的 Key ~~~ ~~~ hvals <name> #获取 Hash 内所有的 Value ~~~ ~~~ hincrby <name> <key> <count> #指定 Hash 内指定 Key 的 Value 增量 ~~~ # Zset(有序集合) ~~~ zadd <name> <score1> <value1> <score2> <value2>... #添加一个/多个值(score 为数字,标识符) ~~~ ~~~ zrange/zrevrange <name> <start> <end> #获取指定区间的值(升序/降序) ~~~ ~~~ zrangebyscore <name> <minScore:e.g.-inf> <maxScore:e.g.+inf> [withscores] #根据 score 从小到大排序,同时输出每个值的 Score(可选参数) ~~~ ~~~ zrem <name> <value> #移除指定元素 ~~~ ~~~ zcard <name> #获取元素个数 ~~~ ~~~ zcount <name> <start> <end> #获取指定区间成员数量 ~~~ # Geospatial(地理位置) ~~~ geoadd <key> <经度> <纬度> <name>... #添加(多个)地理位置 ~~~ ~~~ geopos <key> <name>... #获取(多个)地理位置 ~~~ ~~~ geodist <key> <name1> <name2> <unit> #获取两个地理位置间的距离,unit 可为 m, km, mi, ft ~~~ ~~~ georadius <key> <经度> <纬度> <半径> <unit> [withdist(直线距离)] [withcoord(经纬度)] [count ?] #查询指定半径内的地理位置,可限定输出的最大数量 ~~~ ~~~ georadiusbymember <key> <name> <半径> <unit> [withdist(直线距离)] [withcoord(经纬度)] [count ?] #根据 Geo 内的成员来查询指定的半径位置 ~~~ ~~~ geohash <key> <name1> <name2>... #获取地理位置的 Hash 字符串 ~~~ > ***Geospatial is based on Zset, so you can use most of instructions on Geospatial.(?)*** # HyperLogLog(基数统计) ~~~ pfadd <key> <value1> <value2>... #创建元素【自动去重】 ~~~ ~~~ pfcount <key> #统计元素的基数数量 ~~~ ~~~ pfmerge <newKey> <key1> <key2>... #合并多个元素为一个新元素【自动生成并集】 ~~~ # Bitmap(位存储) ~~~ setbit <key> <offset> <value> #添加位存储记录,offset 必须为数字,value 必须为 0 或 1(e.g. 记录周一已打卡:setbit sign 0 1) ~~~ ~~~ getbit <key> <offset> #查询对应的 value ~~~ ~~~ bitcount <key> #根据 key 获取 value 为 1 的总数 ~~~ # Transaction(事务) ``` multi #开启事务 set k1 v1 set k2 v2 ... #命令入队 exec #执行事务 discard #取消事务 # Redis 事务不保证原子性,但保证一次性、顺序性、排他性。 # 命令入队过程中,若出现语法错误,则所有命令不会执行。其他情况则会执行没有问题的命令。 ``` ## 实现乐观锁 ~~~ watch <key> #监视一个 key,若在一个事务中要更改这个值,但事务尚未执行时,value 被其他线程修改,则会使该事务执行失败。 unwatch #取消监视 #PS:悲观锁则为每次拿数据时都会上锁,影响执行效率;乐观锁只会在数据更新时判断,若被别人更新了才会上锁。 ~~~ # Persistence(持久化) ## RDB 在 x 秒内新增了 x 条记录,则会保存当前所有数据为快照(.rdb)文件。 非实时同步,效率高,但突然宕机可能会丢失一部分数据。 ## AOF 记录每一次增加记录的命令到一个 .aof 文件,在 Redis 重载时读取并自动执行所记录的命令。 根据自定义的间隔时间实时同步,效率较低,突然宕机丢失数据的概率比 RDB 低。 ## RDB/AOF 修复 可以使用 ```redis-check-rdb``` 和 ```redis-check-aof``` 来尝试修复损坏的数据。 # Pub/Sub(发布/订阅) ``` subscribe <channel> #订阅一个频道 ``` ``` publish <channel> <message> #发送一条消息到频道 ``` ``` unsubscribe <channel> #取消订阅一个频道 ``` # Replication(主从复制) ## 基本概念 Redis 服务器启动时,默认为主机(master)。 若需要搭建一主多从环境,需要修改每台主机的 config 文件的值避免冲突,包括但不限于:port、log、rdb、pid 和 config 本身的文件名。 主机可以读写,从机(slave)只能读。一个从机只能连接一个主机。(甚至从机也能连接从机,就会形成链状结构XD) 从机每次连接到主机时,都会执行**全量复制**。之后主机每添加一条新记录,每台从机都会执行**增量复制**。 从机使用命令连接主机是临时的,重启后将会默认变为主机。若需永久变为从机需要修改配置文件的值。 主机宕机时,从机仍为从机,在主机恢复后仍可用。 ## 基本命令 ``` info replication #查看当前主机的主从信息 ``` ``` slaveof <host> <port> #连接到主机(认老大) ``` ``` slaveof no one #将从机转为主机(谋朝篡位) ``` # Sentinel(哨兵) **哨兵**可以监控主机是否故障,主服务器宕机后,**哨兵**可以根据投票数自动切换主从服务器。 哨兵的配置文件的值之一: ``` sentinel monitor <hostname> <host> <port> <count> ``` <hostname> 可以自定义,<count> 为该哨兵代表有多少个哨兵认为该节点不可达,则会开启故障转移,是投票算法所用到的决定性数字。 在 Terminal 执行 redis-sentinel <configname> 可以启动哨兵。 哨兵还有很多功能和配置,比如哨兵也能监控哨兵,其他具体的信息在此不赘述。 # 缓存穿透、击穿和雪崩 ## 穿透 缓存中没有业务所需要的信息,而导致请求全打在了数据库上。 解决方案:1、布隆过滤器(对可能查询的参数以 Hash 形式存储,在控制层先进性校验,不符合则丢弃) 2、缓存空对象 ## 击穿 某个 key 过于热点,不停地扛着高并发,当这个 key 失效时,大量请求打在数据库上。 解决方案:1、设置热点数据永不过期 2、加互斥锁 ## 雪崩 缓存中的信息大面积过期失效,导致所有请求全打在了数据库上。 解决方案:1、Redis 高可用(多搞集群/异地多活)2、限流降级 3、数据预热(把可能被大量请求的数据先加载到缓存中) Last modification:September 22, 2021 © Allow specification reprint
Comment here is closed