企业级Redis开发运维从入门到实践 (3)—Redis API的使用和理解

Redis API的使用和理解

通用命令

这里只简单介绍六个常用针对key(键值)的通用命令

  • keys:KEYS [pattern] 查找所有符合给定模式 pattern 的 key ,keys命令一般不再生产环境使用,数据量大时处理速度慢,会照成阻塞。可以做热备从节点scan
//KEYS * 匹配数据库中所有 key 。
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> set php good
OK
127.0.0.1:6379> set java best
OK
127.0.0.1:6379> keys *
1) "java"
2) "php"
3) "hello"

//KEYS h*llo 匹配 hllo 和 heeeeello 等。
127.0.0.1:6379> mset hello world hehe haha php phe his
OK
127.0.0.1:6379> keys he*
1) "hehe"
2) "hello"

//KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo 。
127.0.0.1:6379> keys he[h-l]*
1) "hehe"
2) "hello"

//KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
127.0.0.1:6379> keys ph?
1) "phe"
2) "php"

//特殊符号用 \ 隔开
  • dbsize:返回当前数据库的 key 的数量。
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 k4 v4
OK
127.0.0.1:6379> dbsize
(integer) 4
127.0.0.1:6379> sadd myset a b c d e
(integer) 5
127.0.0.1:6379> dbsize
(integer) 5
  • exists key:检查给定 key 是否存在,存在返回1,不存在返回0。
127.0.0.1:6379> set a b
OK
127.0.0.1:6379> exists a
(integer) 1
127.0.0.1:6379> del a
(integer) 1
127.0.0.1:6379> exists a
(integer) 0
  • del key [key …]:删除给定的一个或多个 key ,不存在的 key 会被忽略。
127.0.0.1:6379> set a b
OK
127.0.0.1:6379> get a
"b"
127.0.0.1:6379> del a
(integer) 1
127.0.0.1:6379> get a
(nil)
  • expire key seconds:为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
127.0.0.1:6379> set cache_page "www.google.com"
OK
127.0.0.1:6379> expire cache_page 30  # 设置过期时间为 30 秒
(integer) 1
127.0.0.1:6379> ttl cache_page    # 查看剩余生存时间
(integer) 23
127.0.0.1:6379> expire cache_page 30000   # 更新过期时间
(integer) 1
127.0.0.1:6379> ttl cache_page
(integer) 29996
  • ttl key:以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
# 不存在的 key
127.0.0.1:6379> flushDB
OK
127.0.0.1:6379> ttl key
(integer) -2

# key 存在,但没有设置剩余生存时间
127.0.0.1:6379> set key value
OK
127.0.0.1:6379> ttl key
(integer) -1

# 有剩余生存时间的 key
127.0.0.1:6379> expire key 10086
(integer) 1
127.0.0.1:6379> ttl key
(integer) 10084
  • persist key:移除给定 key 的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。
127.0.0.1:6379> set mykey "Hello"
OK
127.0.0.1:6379> expire mykey 10  # 为 key 设置生存时间
(integer) 1
127.0.0.1:6379> ttl mykey
(integer) 10
127.0.0.1:6379> persist mykey    # 移除 key 的生存时间
(integer) 1
127.0.0.1:6379> ttl mykey
(integer) -1
  • type key:返回 key 所储存的值的类型(string、hash、list、set、zset、none)。
127.0.0.1:6379> set a b
OK
127.0.0.1:6379> type a
string
127.0.0.1:6379> sadd myset 1 2 3
(integer) 3
127.0.0.1:6379> type myset
set
时间复杂度
命令 时间复杂度
keys O(n)
dbsize O(1)
del O(1)
exists O(1)
expire O(1)
type O(1)

Redis 命令参考

数据结构和内部编码

对于Redis来说每种数据结构都有自己的内部编码,例如hash结构,内部编码可能hashtable(哈希表)或者ziplist(压缩列表)。

企业级Redis开发运维从入门到实践 (3)—Redis API的使用和理解_第1张图片

为什么要给每种数据结构设置内部编码?

  1. 可以改进内部编码,而对外的数据结构和命令没有影响,这样一旦开发开发出优秀的内部编码,无需改动外部数据结构和命令。
  2. 多种内部编码实现可以在不同场景下发挥各自的优势。例如ziplist比较节省内存,但是在列表元素比较多的情况下,性能会有所下降,这时候Redis会根据配置选项将列表类型的内部实现转换为linkedlist。

redisObject(对象系统)
redisObject是我们使用redis存储之后,实际在内存中保存的对象。
企业级Redis开发运维从入门到实践 (3)—Redis API的使用和理解_第2张图片

单线程架构

单线程的模式下,保证前一次操作执行完后,下一次操作才能执行;完全是一个串行的结构。
企业级Redis开发运维从入门到实践 (3)—Redis API的使用和理解_第3张图片

单线程为什么这么快

  1. 完全基于内存:绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
  2. 数据结构简单:对数据操作也简单,Redis中的数据结构是专门进行设计的;
  3. 采用单线程避免了不必要的上下文切换和竞争条件:也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
  4. 非阻塞IO:使用多路I/O复用模型;
  5. 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

以上几点都比较好理解,下边我们针对多路 I/O 复用模型进行简单的探讨:

  1. 多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
  2. 这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。

企业级Redis开发运维从入门到实践 (3)—Redis API的使用和理解_第4张图片

单线程使用注意

  1. 每次只执行一条命令
  2. 拒绝长(即执行慢)命令,长命令:keys、flushall、flushdb、slow lua script、mutil/exec、operate、big value(collection)
  3. 其实不是单线程,fysnc file descriptor、close file descriptor。

你可能感兴趣的:(Redis)