前言

这里将持续整理一些 Redis 核心笔记

中文社区: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选项作用一样,用于更新

常用命令

> 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

> 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

> 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

创建哈希类型的键值

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

127.0.0.1:6379> hset user name "LotusChing" age 21
(error) ERR wrong number of arguments for 'hset' command

获取哈希键中的field值

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

127.0.0.1:6379> hekys user
1) "name"
2) "age"

获取哈希键中的所有field的value

127.0.0.1:6379> hvals user
1) "LotusChing"
2) "21"

删除哈希键中某个field

127.0.0.1:6379> hdel user age
(integer) 1
127.0.0.1:6379> hkeys user
1) "name"

统计哈希中field的个数

127.0.0.1:6379> hkeys user
1) "name"
2) "age"
3) "gender"
127.0.0.1:6379> hlen user
(integer) 3

批量设置哈希键的field

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

127.0.0.1:6379> hmget user name age gender
1) "LotusChing"
2) "21"
3) "Male"

判断哈希键中field是否存在

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

127.0.0.1:6379> hgetall user
1) "name"
2) "LotusChing"
3) "age"
4) "21"
5) "gender"
6) "Male"

ZSET

> 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"

参考资料:

4. 通用命令

  • keys

  • dbsize

  • del

  • exists

  • expire key seconds

  • ttl

  • persist

  • type

过期时间

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

书籍推荐