|
| 1 | +# 初探 Redis |
| 2 | + |
| 3 | +## Redis 简介 |
| 4 | + |
| 5 | +Redis 是一个速度非常快的非关系型数据库(non-relational database)/ NoSQL 数据库。 |
| 6 | + |
| 7 | +Redis 不使用表,也不会预定义或者强制去要求用户对 Redis 存储不同的数据进行关联。 |
| 8 | + |
| 9 | +> **Redis 为什么速度非常快?** |
| 10 | +
|
| 11 | +- **纯内存操作
3942
** |
| 12 | + |
| 13 | + 数据存在内存中,类似于 HashMap。HashMap 的优势就是查找和操作的时间复杂度都是 O(1) |
| 14 | + |
| 15 | +- **数据结构简单** |
| 16 | + |
| 17 | + 不仅数据结构简单,而且对数据操作也简单 |
| 18 | + |
| 19 | +- **单线程** |
| 20 | + |
| 21 | + 避免了频繁的上下文切换,也不存在多进程或者多线程导致的切换而消耗 CPU 资源,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗 |
| 22 | + |
| 23 | +## Redis 数据结构 |
| 24 | + |
| 25 | +Redis 存储键(key)和 5 种不同类型的值(value)之间的映射。这 5 中类型分别为: |
| 26 | + |
| 27 | +STRING(字符串)、LIST(列表)、HASH(散列)、SET(集合)和 ZSET(有序集合)。 |
| 28 | + |
| 29 | +| 结构类型 | 结构存储的值 | |
| 30 | +| :------: | :----------------------------------------------------------: | |
| 31 | +| STRING | 字符串、整数或者浮点数 | |
| 32 | +| LIST | 一个链表,链表上的每个节点都包含了一个字符串 | |
| 33 | +| HASH | 包含键值对的无序散列表 | |
| 34 | +| SET | 包含字符串的无序收集器 | |
| 35 | +| ZSET | 字符串成员(member)与浮点数(score)分值之间的有序映射,<br/>元素的排列顺序由分值大小决定 | |
| 36 | + |
| 37 | + |
| 38 | + |
| 39 | +### 1. STRING(字符串) |
| 40 | + |
| 41 | +字符串示例,键为 hello,值为 world: |
| 42 | + |
| 43 | +<div align="center"><img src="https://gitee.com/duhouan/ImagePro/raw/master/redis/redis_1.png" width="350px"/></div> |
| 44 | + |
| 45 | +- 字符串命令 |
| 46 | + |
| 47 | + | 命令 | 行为 | 时间复杂度 | |
| 48 | + | :--: | :------------------------------------------------: | :--------: | |
| 49 | + | GET | 获取存储在给定键中的值 | O(1) | |
| 50 | + | SET | 设置存储在给定键中的值 | O(1) | |
| 51 | + | DEL | 删除存储在给定键中的值(这个命令可以用于所有类型) | O(1) | |
| 52 | + | INCR | 自增 | O(1) | |
| 53 | + | DECR | 自减 | O(1) | |
| 54 | + |
| 55 | +- 使用 |
| 56 | + |
| 57 | + ```html |
| 58 | + 127.0.0.1:6379> set hello world |
| 59 | + OK |
| 60 | + 127.0.0.1:6379> get hello |
| 61 | + "world" |
| 62 | + 127.0.0.1:6379> del hello |
| 63 | + (integer) 1 |
| 64 | + 127.0.0.1:6379> get hello |
| 65 | + (nil) |
| 66 | + ``` |
| 67 | + |
| 68 | + ```html
| 69 | + 127.0.0.1:6379> set num 1 |
| 70 | + OK |
| 71 | + 127.0.0.1:6379> incr num |
| 72 | + (integer) 2 |
| 73 | + 127.0.0.1:6379> get num |
| 74 | + "2" |
| 75 | + ``` |
| 76 | + |
| 77 | + |
| 78 | +### 2. LIST(列表) |
| 79 | + |
| 80 | +list-key 是一个包含 3 个元素的列表键,列表中的元素是可以重复的: |
| 81 | + |
| 82 | +<div align="center"><img src="https://gitee.com/duhouan/ImagePro/raw/master/redis/redis_2.png" width="350px"/></div> |
| 83 | + |
| 84 | +- 列表命令 |
| 85 | + |
| 86 | + | 命令 | 行为 | 时间复杂度 | |
| 87 | + | :----: | :--------------------------------------: | :--------: | |
| 88 | + | LPUSH | 将给定值推入链表的左端 | O(N) | |
| 89 | + | RPUSH | 将给定值推入链表的右端 | O(N) | |
| 90 | + | LRANGE | 获取列表在给定范围上的所有值 | O(N) | |
| 91 | + | LINDEX | 获取列表在给定位置上的单个元素 | O(N) | |
| 92 | + | LPOP | 从链表的左端弹出一个值,并返回被弹出的值 | O(1) | |
| 93 | + |
| 94 | +- 使用 |
| 95 | + |
| 96 | + ```html |
| 97 | + 127.0.0.1:6379> rpush list-key item |
| 98 | + (integer) 1 |
| 99 | + 127.0.0.1:6379> rpush list-key item2 |
| 100 | + (integer) 2 |
| 101 | + 127.0.0.1:6379> rpush list-key item |
| 102 | + (integer) 3 # 返回的列表长度 |
| 103 | + ``` |
| 104 | + |
| 105 | + ```html |
| 106 | + 127.0.0.1:6379> lrange list-key 0 -1 |
| 107 | + 1) "item" |
| 108 | + 2) "item2" |
| 109 | + 3) "item" |
| 110 | + # 使用 0 为范围的开始索引,-1 为范围索引的结束索引,可以去除列表包含的所有元素 |
| 111 | + 127.0.0.1:6379> lindex list-key 1 |
| 112 | + "item2" |
| 113 | + ``` |
| 114 | + |
| 115 | + ```html |
| 116 | + 127.0.0.1:6379> lpop list-key |
| 117 | + "item" |
| 118 | + 127.0.0.1:6379> lrange list-key 0 -1 |
| 119 | + 1) "item2" |
| 120 | + 2) "item" |
| 121 | + ``` |
| 122 | + |
| 123 | + |
| 124 | +### 3. HASH(散列) |
| 125 | + |
| 126 | +hash-key 是一个包含两个键值对的散列键: |
| 127 | + |
| 128 | +<div align="center"><img src="https://gitee.com/duhouan/ImagePro/raw/master/redis/redis_4.png" width="350px"/></div> |
| 129 | + |
| 130 | +- 散列命令 |
| 131 | + |
| 132 | + | 命令 | 行为 | 时间复杂度 | |
| 133 | + | :-----: | :--------------------------------------: | :--------: | |
| 134 | + | HSET | 在散列表中关联其给定的键值对 | O(1) | |
| 135 | + | HGET | 获取指定散列键的值 | O(1) | |
| 136 | + | HGETALL | 获取散列包含的所有键值对 | O(N) | |
| 137 | + | HDEL | 如果给定键存在于散列表中,那么移除这个键 | O(N) | |
| 138 | + |
| 139 | +- 使用 |
| 140 | + |
| 141 | + ```html |
| 142 | + 127.0.0.1:6379> hset hash-key sub-key1 value1 |
| 143 | + (integer) 1 |
| 144 | + 127.0.0.1:6379> hset hash-key sub-key2 value2 |
| 145 | + (integer) 1 |
| 146 | + 127.0.0.1:6379> hset hash-key sub-key1 value2 |
| 147 | + (integer) 0 |
| 148 | + 127.0.0.1:6379> hgetall hash-key |
| 149 | + 1) "sub-key1" |
| 150 | + 2) "value2" |
| 151 | + 3) "sub-key2" |
| 152 | + 4) "value2" |
| 153 | + ``` |
| 154 | + |
| 155 | + ```html |
| 156 | + 127.0.0.1:6379> hdel hash-key sub-key2 |
| 157 | + (integer) 1 |
| 158 | + 127.0.0.1:6379> hdel hash-key sub-key2 |
| 159 | + (integer) 0 |
| 160 | + 127.0.0.1:6379> hget hash-key sub-key1 |
| 161 | + "value2" |
| 162 | + 127.0.0.1:6379> hgetall hash-key |
| 163 | + 1) "sub-key1" |
| 164 | + 2) "value2" |
| 165 | + ``` |
| 166 | + |
| 167 | + |
| 168 | +### 4. SET(集合) |
| 169 | + |
| 170 | +set-key 是一个包含 3 个元素的集合键: |
| 171 | + |
| 172 | +<div align="center"><img src="https://gitee.com/duhouan/ImagePro/raw/master/redis/redis_3.png" width="350px"/></div> |
| 173 | + |
| 174 | + |
| 175 | + |
| 176 | +- 集合命令 |
| 177 | + |
| 178 | + | 命令 | 行为 | 时间复杂度 | |
| 179 | + | :-------: | :------------------------------------------: | :--------: | |
| 180 | + | SADD | 将给定元素添加到集合 | O(N) | |
| 181 | + | SMEMBERS | 返回集合包含的所有元素 | O(N) | |
| 182 | + | SREM | 如果给定的元素存在于集合中,那么一处这个元素 | O(N) | |
| 183 | + | SISMEMBER | 检查给定元素是否存在于集合中 | O(1) | |
| 184 | + |
| 185 | +- 使用 |
| 186 | + |
| 187 | + ```html |
| 188 | + 127.0.0.1:6379> sadd set-key item |
| 189 | + (integer) 1 |
| 190 | + 127.0.0.1:6379> sadd set-key item2 |
| 191 | + (integer) 1 |
| 192 | + 127.0.0.1:6379> sadd set-key item3 |
| 193 | + (integer) 1 |
| 194 | + 127.0.0.1:6379> sadd set-key item |
| 195 | + (integer) 0 |
| 196 | + 127.0.0.1:6379> smembers set-key |
| 197 | + 1) "item" |
| 198 | + 2) "item3" |
| 199 | + 3) "item2" |
| 200 | + ``` |
| 201 | + |
| 202 | + ```html |
| 203 | + 127.0.0.1:6379> sismember set-key item4 |
| 204 | + (integer) 0 |
| 205 | + 127.0.0.1:6379> sismember set-key item |
| 206 | + (integer) 1 |
| 207 | + ``` |
| 208 | + |
| 209 | + ```html |
| 210 | + 127.0.0.1:6379> srem set-key item |
| 211 | + (integer) 1 |
| 212 | + 127.0.0.1:6379> srem set-key item |
| 213 | + (integer) 0 |
| 214 | + 127.0.0.1:6379> smembers set-key |
| 215 | + 1) "item3" |
| 216 | + 2) "item2" |
| 217 | + ``` |
| 218 | + |
| 219 | + |
| 220 | + |
| 221 | +### 5. ZSET(有序集合) |
| 222 | + |
| 223 | +zset-key 是已一个包含 2 个元素的有序集合键: |
| 224 | + |
| 225 | +<div align="center"><img src="https://gitee.com/duhouan/ImagePro/raw/master/redis/redis_5.png" width="350px"/></div> |
| 226 | + |
| 227 | +- 有序集合命令 |
| 228 | + |
| 229 | + | 命令 | 行为 | 时间复杂度 | |
| 230 | + | :-----------: | :------------------------------------------------------: | :---------: | |
| 231 | + | ZADD | 将一个带有给定分值的成员添加到有序集合里面 | O(Mlog(N)) | |
| 232 | + | ZRANGE | 根据元素在有序排列中所处的位置,从有序集合中获取多个元素 | O(log(N)+M) | |
| 233 | + | ZRANGEBYSCORE | 获取有序集合在给定范围内的所有元素 | O(log(N)+M) | |
| 234 | + | ZREM | 如果给定成员存在于有序集合,那么移除这个成员 | O(Mlog(N)) | |
| 235 | + |
| 236 | +- 使用 |
| 237 | + |
| 238 | + ```html |
| 239 | + 127.0.0.1:6379> zadd zset-key 728 member1 |
| 240 | + (integer) 1 |
| 241 | + 127.0.0.1:6379> zadd zset-key 982 member2 |
| 242 | + (integer) 1 |
| 243 | + 127.0.0.1:6379> zadd zset-key 982 member2 |
| 244 | + (integer) 0 |
| 245 | + 127.0.0.1:6379> zrange zset-key 0 -1 withscores |
| 246 | + 1) "member1" |
| 247 | + 2) "728" |
| 248 | + 3) "member2" |
| 249 | + 4) "982" |
| 250 | + ``` |
| 251 | + |
| 252 | + ```html |
| 253 | + 127.0.0.1:6379> zrangebyscore zset-key 0 800 withscores |
| 254 | + 1) "member1" |
| 255 | + 2) "728" |
| 256 | + ``` |
| 257 | + |
| 258 | + ```html |
| 259 | + 127.0.0.1:6379> zrem zset-key member1 |
| 260 | + (integer) 1 |
| 261 | + 127.0.0.1:6379> zrem zset-key member1 |
| 262 | + (integer) 0 |
| 263 | + 127.0.0.1:6379> zrange zset-key 0 -1 withscores |
| 264 | + 1) "member2" |
| 265 | + 2) "982" |
| 266 | + ``` |
| 267 | + |
| 268 | + |
| 269 | +> **扩展** |
| 270 | +
|
| 271 | +- [Redis 常用命令时间复杂度](https://blog.csdn.net/zzm848166546/article/details/80360665) |
| 272 | +- [Redis 命令大全](https://redis.io/commands) |
| 273 | + |
| 274 | + |
| 275 | + |
| 276 | +## 牛刀小试 |
| 277 | + |
| 278 | +使用 Redis 构建一个简单的文章点赞网站的后端。 |
| 279 | + |
| 280 | +### 1. 文章投票 |
| 281 | + |
| 282 | +需要实现的功能: |
| 283 | + |
| 284 | +- 一篇文章如 |
| 285 | + |
| 286 | +- 可以对文章进行点赞; |
| 287 | +- 按文章的发布时间或者文章的评分进行排序 |
| 288 | +- 评分计算方式:点赞数 * 432 + 1970年1月1日到现在为止的秒数 |
| 289 | + |
| 290 | + |
| 291 | + |
| 292 | + |
| 293 | + |
| 294 | +### 2. 发布文章 |
| 295 | + |
| 296 | + |
| 297 | + |
| 298 | +### 3. 文章分组 |
| 299 | + |
| 300 | + |
| 301 | + |
| 302 | + |
| 303 | + |
| 304 | + |
| 305 | + |
| 306 | +> 完整代码请参考:[Redis in action](https://github.com/josiahcarlson/redis-in-action) |
0 commit comments