# 前言 这里将持续整理一些 Redis 核心笔记 中文社区:[redis.cn](http://redis.cn/) # 一、Redis ## 1. 简介 单线程为什么这么快? 1. 纯内存 2. 非阻塞IO 3. 避免线程切换和竞争消耗 单线程Redis注意事项 1. 一次只运行一条命令 2. 拒绝长(慢)命令,例如:keys、flushall、flushdb、slow lua script、mutil/exec、operate big value(collection) 3. Redis其实不是单线程,fysnc file descriptor进行持久化 特性 1. 速度快 2. 持久化 3. 多钟数据结构 4. 支持多种编程语言 5. 功能丰富 6. 简单 7. 主从复制 8. 高可用,分布式 ## 2. 应用场景 缓存系统 排行榜 计数器 社交网络 消息队列系统 实时系统 ## 3. 数据类型

| 结构类型 | 结构存储的值 | 结构的读写能力 | | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | STRING | 可以是字符串、整数或者浮点数 | 对整个字符串或者字符串的其中一部分执行操作
对整数和浮点数执行自增或自减操作 | | LIST | 一个链表,链表上的每个节点都包含了一个字符串 | 从两端压入或者弹出元素
对单个或者多个元素
进行修剪,只保留一个范围内的元素 | | SET | 包含字符串的无序收集器(unordered collection),并且被包含的每个字符串都是独一无二、各不相同的 | 添加、获取、移除单个元素
检查一个元素是否存在于集合中
计算交集、并集、差集
从集合里面随机获取元素 | | HAST | 包含键值对的无序散列表 | 添加、获取、移除单个键值对
获取所有键值对
检查某个键是否存在 | | ZSET | 字符串成员(member)与浮点数分值(score)之间的有序映射,元素的排列顺序由分值的大小决定 | 添加、获取、删除元素
根据分值范围或者成员来获取元素
计算一个键的排名 | ### STRING
**设置语法** ``` set key value [EX seconds] [PX ms] [nx|xx] ``` - key: 键名 - value: 键值 - ex seconds: 键秒级过期时间 - ex ms: 键毫秒及过期时间 - nx: 键不存在才能设置,setnx和nx选项作用一样,用于添加,分布式锁的实现 - xx: 键存在才能设置,setxx和xx选项作用一样,用于更新 **常用命令** ```redis > set hello world OK > get hello "world" > del hello (integer) 1 > get hello (nil) ``` 书中提到一个有趣的概念,批量操作mget可以提供效率节省时间 逐条 get/se t的时间消耗公式: ``` n次get/set时间 = n次网络时间 + n次命令时间 ``` 批量get/set的时间消耗公式: `n次get/set时间 = 1次网络时间 + n次命令时间` 合理的使用批量操作可以提高Redis性能,但是注意不要量太大,**如果过量的话可能会导致Redis阻塞** **时间复杂度** - set: O(1) - get: O(1) - del: O(k),k为键的个数 - mget: O(k),k为键的个数 - mset: O(k),k为键的个数 - append: O(1) - str: O(1) - getrange: O(n), n为字符串的长度 **内部编码** - int: 8字节长整型 - embstr: 小于39字节值 - raw: 大于39字节的值 **典型场景** - 缓存 - 计算器 - 分布式锁 **场景** - 缓存 - 计算器 - 分布式锁 ### LIST
```shell > rpush list-key item (integer) 1 > rpush list-key item2 (integer) 2 > rpush list-key item (integer) 3 > lrange list-key 0 -1 1) "item" 2) "item2" 3) "item" > lindex list-key 1 "item2" > lpop list-key "item" > lrange list-key 0 -1 1) "item2" 2) "item" ``` ### SET
```shell > sadd set-key item (integer) 1 > sadd set-key item2 (integer) 1 > sadd set-key item3 (integer) 1 > sadd set-key item (integer) 0 > smembers set-key 1) "item" 2) "item2" 3) "item3" > sismember set-key item4 (integer) 0 > sismember set-key item (integer) 1 > srem set-key item2 (integer) 1 > srem set-key item2 (integer) 0 > smembers set-key 1) "item" 2) "item3" ``` ### HASH
**创建哈希类型的键值** ```shell 127.0.0.1:6379> hset user name LotusChing (integer) 1 127.0.0.1:6379> hset user age 21 (integer) 1 127.0.0.1:6379> hset user gender "Male" (integer) 1 ``` HSET 不支持创建一次性创建多field ```shell 127.0.0.1:6379> hset user name "LotusChing" age 21 (error) ERR wrong number of arguments for 'hset' command ``` **获取哈希键中的field值** ```shell 127.0.0.1:6379> hget user name "LotusChing" 127.0.0.1:6379> hget user age "21" 127.0.0.1:6379> hget user gender "Male" ``` HGET 不支持一次获取多个field **获取哈希键中的fields** ```shell 127.0.0.1:6379> hekys user 1) "name" 2) "age" ``` **获取哈希键中的所有field的value** ```shell 127.0.0.1:6379> hvals user 1) "LotusChing" 2) "21" ``` **删除哈希键中某个field** ```shell 127.0.0.1:6379> hdel user age (integer) 1 127.0.0.1:6379> hkeys user 1) "name" ``` **统计哈希中field的个数** ```shell 127.0.0.1:6379> hkeys user 1) "name" 2) "age" 3) "gender" 127.0.0.1:6379> hlen user (integer) 3 ``` **批量设置哈希键的field** ```shell 127.0.0.1:6379> hmset user name "LotusChing" age 21 gender "Male" OK 127.0.0.1:6379> hkeys user 1) "name" 2) "age" 3) "gender" 127.0.0.1:6379> hvals user 1) "LotusChing" 2) "21" 3) "Male" ``` **批量获取哈希键中field的value** ```shell 127.0.0.1:6379> hmget user name age gender 1) "LotusChing" 2) "21" 3) "Male" ``` **判断哈希键中field是否存在** ```shell 127.0.0.1:6379> hexists user name (integer) 1 127.0.0.1:6379> hexists user hobbies (integer) 0 ``` **一次性获取哈希键中所有的fields和values** 注意:尽量避免使用`hgetall`,因为如果哈希键field过多的话,可能会导致Redis阻塞,建议使用`hmget`获取所需哈希键中的field值,或者采用`hscan` ```shell 127.0.0.1:6379> hgetall user 1) "name" 2) "LotusChing" 3) "age" 4) "21" 5) "gender" 6) "Male" ``` ### ZSET
```shell > zadd zset-key 728 member1 (integer) 1 > zadd zset-key 982 member0 (integer) 1 > zadd zset-key 982 member0 (integer) 0 > zrange zset-key 0 -1 withscores 1) "member1" 2) "728" 3) "member0" 4) "982" > zrangebyscore zset-key 0 800 withscores 1) "member1" 2) "728" > zrem zset-key member1 (integer) 1 > zrem zset-key member1 (integer) 0 > zrange zset-key 0 -1 withscores 1) "member0" 2) "982" ``` 参考资料: - [Chapter 1: Getting to know Redis | Redis Labs](https://redislabs.com/ebook/part-1-getting-started/chapter-1-getting-to-know-redis/) ## 4. 通用命令 - keys - dbsize - del - exists - expire key seconds - ttl - persist - type **过期时间** ```shell redis> SET cache_page "www.google.com" OK redis> EXPIRE cache_page 30 # 设置过期时间为 30 秒 (integer) 1 redis> TTL cache_page # 查看剩余生存时间 (integer) 23 redis> EXPIRE cache_page 30000 # 更新过期时间 (integer) 1 redis> TTL cache_page (integer) 29996 ``` ## 6. Redis持久化 Redis 持久化之RDB和AOF - ITDragon龙 - 博客园 https://www.cnblogs.com/itdragon/p/7906481.html # 参考资料 - [ops_book/listlie-886829.md at master · LotusChing/ops_book](ops_book/listlie-886829.md at master · LotusChing/ops_book) # 更新日志 - 2018/9/4 init1.0