Redis学习笔记

  • 简介

          Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、高性能的Key-Value 数据库。

  • 数据类型

          Redis 的 key 是字符串类型,但是 key 中不能包括边界字符,由于 key 不是边界安全的字符串,所像"my  key"和"mykey\n" 这样包含空格和换行的 key 是不允许的。

  • key 相关指令介绍

exits  key 检测指定 key 是否存在,返回 1 表示存在,0 不存在

del  key1 key2......keyN 删除给定 key,返回删除 key 的数目,0 表示给定 key 都不存在

type key 返回给定 key 值的类型。返回 none 表示 key 不存在,string 字符类型,list 链表 类型 set 无序集合类型.....

keys  pattern 返回匹配指定模式的所有 key

randomkey 返回从当前数据库中随机选择的一个 key,如果当前数据库是空的,返回空串

rename oldkey  newkey 重命名一个 key,如果 newkey 存在,将会被覆盖,返回 1 表示成功, 0 失败。可能是 oldkey 不存在或者和 newkey 相同。

renamenx oldkey   newkey 同上,但是如果 newkey 存在返回失败.

echo 打印命令

config get  实时传输收到的请求(返回相关的配置信息) 后面加* 表示返回所有配置

expire key seconds 为 key 指定过期时间,单位是秒。返回 1 成功,0 表示 key 已经设置过过 期时间或者不存在。

ttl  key 返回设置过过期时间key的剩余过期秒数。-1表示key不存在或者未设置过期时间。

persist  key 取消过期时间

select  db-index 通过索引选择数据库,默认连接的数据库是 0,默认数据库数是 16 个。返回 1 表示成功,0 失败

info 获取数据库信息

dbsize  查看数据库的key数量

move  key db-index 将 key 从当前数据库移动到指定数据库。返回 1 表示成功。0 表示 key 不存在或者已经在指定数据库中

flushdb 清空当前数据库,flushall 清空所有数据库

  •  Redis 的 vaule

    redis 提供五种数据类型:string,hash,list,set 及 sorted set(zset)

 

       1.string 类型:

        string 是最基本的类型,而且 string 类型是二进制安全的。意思是 redis 的 string 可以 包含任何数据。比如 jpg 图片或者序列化的对象。从内部实现来看其实 string 可以看作 byte数组,最大上限是 1G 字节。

        string 类型数据操作指令简介

set  key  value 设置 key 对应 string 类型的值,返回 1 表示成功,0 失败。

setnx key value 如果 key 不存在,设置 key 对应 string 类型的值。如果 key 已经存在,返 回 0。

get  key 获取 key 对应的 string 值,如果 key 不存在返回 nil

getset  key value 先获取 key 的值,再设置 key 的值。如果 key 不存在返回 nil。

mget  key1 key2 ......keyN 一次获取多个 key 的值,如果对应 key 不存在,则对应返回 nil。

mset  key1 value1......keyN valueN 一次设置多个 key 的值,成功返回 1 表示所有的值都设置 了,失败返回 0 表示没有任何值被设置。

msetnx  key1 value1......keyN valueN 一次设置多个 key 的值,但是不会覆盖已经存在的 key

incr key 对 key 的值做++操作,并返回新的值。注意 incr 一个不是 int 的 value 会返回错 误,incr 一个不存在的 key,则设置 key 值为 1。

decr key 对 key 的值做--操作,decr 一个不存在 key,则设置 key 值为-1。

incrby key integer 对 key 加上指定值 ,key 不存在时候会设置 key,并认为原来的 value 是 0。

decrby  key integer 对 key 减去指定值。decrby 完全是为了可读性,我们完全可以通过 incrby 一个负值来实现同样效果,反之一样。

 

        2. hash 类型

         hash 是一个 string 类型的 field 和 value 的映射表。添加,删除操作都是 O(1)(平均) 。 hash 特别适合用于存储对象。相对于将对象的每个字段存成单个 string 类型。将一个对象 存储在 hash 类型中会占用更少的内存,并且可以更方便的存取整个对象。省内存的原因是 新建一个 hash 对象时开始是用 zipmap(又称为 smallhash)来存储的。这个 zipmap 其实并不是 hash table,但是 zipmap 相比正常的 hash 实现可以节省不少 hash 本身需要的一些元 数据存储开销。尽管 zipmap 的添加,删除,查找都是 O(n),但是由于一般对象的 field 数量都不太多。所以使用 zipmap 也是很快的,也就是说添加删除平均还是 O(1)。如果 field 或者 value的大小超出一定限制后,redis会在内部自动将zipmap替换成正常的hash实现. 这个限制可以在配置文件中指定。 

hash-max-zipmap-entries64                                    #配置字段最多 64 个

hash-max-zipmap-value512                                    #配置 value 最大为 512 字节

 

        hash 类型数据操作指令简介

hset  key  field value 设置 hash field 为指定值,如果 key 不存在,则创建

hget  key  field 获取指定的 hash field。

hmget key filed1....fieldN 获取全部指定的 hash filed。

hmset  key filed1 value1......filedN valueN 同时设置 hash 的多个 field。

hincrby key  field integer 将指定的 hash filed 加上指定值。成功返回 hash filed 变更后的 值。

hexists key  field 检测指定 field 是否存在。

hdel  key field 删除指定的 hash field。

hlen  key 返回指定 hash 的 field 数量。
hkeys key 返回 hash 的所有 field。

hvals key 返回 hash 的所有 value。

hgetall 返回 hash 的所有 filed 和 value

 

       3. list 类型

        list 是一个链表结构,可以理解为一个每个子元素都是 string 类型的双向链表。主要功 能是 push、pop、获取一个范围的所有值等,也可以通过相关操作进行集合的头部或尾部添加删除元素,list既可以作为栈,也可以作为队列来使用(消费者调用rpush方法可以将list作为一个MQ来使用)。操作中 key 理解为链表的名字。

     List 类型数据操作指令简介

lpush  key string 在 key 对应 list 的头部添加字符串元素(栈),先进后出,返回 1 表示成功,0 表示 key 存在但不是 list 类型。

rpush  key string 在 key 对应 list 的尾部添加字符串元素(队列),先进先出。

linsert  key string:插入元素  insert  list名 before 元素名  ,在list中插入某元素在 **之前

llen key 返回 key 对应 list 的长度,如果 key 不存在返回 0,如果 key 对应类型不是 list 返回错误。

lrange key start end 返回指定区间内的元素,下标从 0 开始,负值表示从后面计算,-1 表示 倒数第一个元素 ,key 不存在返回空列表。例:lrange key 0 -1

ltrim key start  end 截取 list 指定区间内元素,成功返回 1,key 不存在返回错误。

lset key index value 设置 list 中指定下标的元素值,成功返回 1,key 或者下标不存在返回 错误。

lrem key count value从 List 的头部(count正数)或尾部(count负数)删除一定数量(count) 匹配 value 的元素,返回删除的元素数量。count 为 0 时候删除全部。

lpop key 从 list 的头部删除并返回删除元素。如果 key 对应 list 不存在或者是空返回 nil, 如果 key 对应值不是 list 返回错误。

rpoplpush 第一步从尾部删除元素,然后第二步从头部加入元素

lindex key index 返回名称为key的list中index位置的元素

rpop key 从 list 的尾部删除并返回删除元素。

blpop key1 ......keyN timeout 从左到右扫描,返回对第一个非空 list 进行 lpop 操作并返回, 比如 blpop list1 list2 list3 0 ,如果 list 不存在 list2,list3 都是非空则对 list2 做 lpop 并返回从 list2 中删除的元素。如果所有的 list 都是空或不存在,则会阻塞 timeout 秒,timeout 为 0 表示一直阻塞。当阻塞时,如果有 client 对 key1...keyN 中的任意 key 进行 push 操作,则第一在这个 key 上被阻塞的 client 会立即返回。如果超时发生,则返回 nil。有点像 unix 的 select 或者 poll。

brpop 同 blpop,一个是从头部删除一个是从尾部删除

 

          4. set 类型

        set 是无序不重复集合,最大可以包含(2 的 32 次方-1)个元素。set 的是通过 hashtable 实现的, 所以添加,删除,查找的复杂度都是 O(1)。hashtable 会随着添加或者删除自动的调整大小。 需要注意的是调整 hashtable 大小时候需要同步(获取写锁)会阻塞其他读写操作。可能不久后就会改用跳表(skip list)来实现。跳表已经在 sortedsets 中使用了。关于 set 集合类型 除了基本的添加删除操作,其它有用的操作还包含集合的取并集(union),交集(intersection), 差集(difference)。通过这些操作可以很容易的实现 SNS 中的好友推荐和 blog 的 tag 功能。

        set 类型数据操作指令简介

sadd key member 添加一个 string 元素到 key 对应 set 集合中,成功返回 1,如果元素以及 在集合中则返回 0,key 对应的 set 不存在则返回错误。

srem key member 从 key 对应 set 中移除指定元素,成功返回 1,如果 member 在集合中不 存在或者 key 不存在返回 0,如果 key 对应的不是 set 类型的值返回错误。

spop key 删除并返回 key 对应 set 中随机的一个元素,如果 set 是空或者 key 不存在返回 nil。

srandmember key 同 spop,随机取 set 中的一个元素,但是不删除元素。

smove srckey dstkey member 从srckey对应set中移除member并添加到dstkey对应set中, 整个操作是原子的。成功返回 1,如果 member 在 srckey 中不存在返回 0,如果 key 不是 set 类型返回错误。

scard key 返回 set 的元素个数,如果 set 是空或者 key 不存在返回 0。

sismember key member 判断 member 是否在 set 中,存在返回 1,0 表示不存在或者 key 不 存在。

sinter key1 key2 ……keyN 返回所有给定 key 的交集。

sinterstore key key1 .......keyN 返回所有给定 key 的交集,并保存交集存到 dstkey 下。

sunion key1 key2 ......keyN 返回所有给定 key 的并集。

sunionstore dst key key1 ......keyN 返回所有给定 key 的并集,并保存并集到 dstkey 下。

sdiff key1 key2......keyN 返回所有给定 key 的差集。

sdiffstore dstkeykey1 ......keyN 返回所有给定 key 的差集,并保存差集到 dstkey 下。 

smembers key 返回key对应set的所有元素,结果是无序的

 

           5. sorted set 类型

           sorted set 是有序集合,它在 set 的基础上增加了一个顺序属性,这一属性在添加修 改元素的时候可以指定,每次指定后,会自动重新按新的值调整顺序。可以理解为有两列的 mysql 表,一列存 value,一列存顺序。操作中 key 理解为 sorted set 的名字。


       Sorted Set 类型数据操作指令简介 

add  key score member 添加元素到集合,元素在集合中存在则更新对应 score。

zrem key  member 删除指定元素,1 表示成功,如果元素不存在返回 0。

zincrby  key incr  member 增加对应 member 的 score 值,然后移动元素并保持 skiplist 保持有 序。返回更新后的 score 值。

zrank key member 返回指定元素在集合中的排名(下标),集合中元素是按 score 从小到大 排序的。

zrevrank  key member 同上,但是集合中元素是按 score 从大到小排序。

zrange  key start  end 类似 lrange 操作从集合中去指定区间的元素。返回的是有序结果

zrevrange  key start  end 同上,返回结果是按 score 逆序的。

zrangebyscore  key  min max 返回集合中 score 在给定区间的元素。

zcount  key  min  max 返回集合中 score 在给定区间的数量。

zcard  key 返回集合中元素个数。

zscore  key element 返回给定元素对应的 score。

zremrangebyrank  key  min max 删除集合中排名在给定区间的元素。

zremrangebyscore  key min  max 删除集合中 score 在给定区间的元素

  • 主从复制

        Redis 主从复制简介

Redis 支持将数据同步到多台从库上,这种特性对提高读取性能非常有益。

1) master 可以有多个 slave。

2) 除了多个 slave 连到相同的 master 外,slave 也可以连接其它 slave 形成图状结构。

3) 主从复制不会阻塞 master。也就是说当一个或多个 slave 与 master 进行初次同步数据 时,master 可以继续处理客户端发来的请求。相反 slave 在初次同步数据时则会阻塞 不能处理客户端的请求。

4) 主从复制可以用来提高系统的可伸缩性,我们可以用多个 slave 专门用于客户端的读 请求,比如 sort 操作可以使用 slave 来处理。也可以用来做简单的数据冗余。

5) 可以在 master 禁用数据持久化,只需要注释掉 master 配置文件中的所有 save 配置,然 后只在 slave 上配置数据持久化

 

        Redis 主从复制的过程介绍

        当设置好 slave 服务器后,slave 会建立和 master 的连接,然后发送 sync 命令。无论是 第一次同步建立的连接还是连接断开后的重新连接,master 都会启动一个后台进程,将数据 库快照保存到文件中,同时 master 主进程会开始收集新的写命令并缓存起来。后台进程完 成写文件后,master 就发送文件给 slave,slave 将文件保存到磁盘上,然后加载到内存恢复 数据库快照到 slave 上。接着 master 就会把缓存的命令转发给 slave。而且后续 master 收到 的写命令都会通过开始建立的连接发送给slave。从master到slave的同步数据的命令和从 客 户端发送的命令使用相同的协议格式。当 master 和 slave 的连接断开时 slave 可以自动重新 建立连接。如果 master 同时收到多个 slave 发来的同步连接命令,只会启动一个进程来写数 据库镜像,然后发送给所有 slave

  •   Redis 事务

        Redis 通过 MULTI 、DISCARD 、EXEC 和 WATCH 四个命令来实现事务功能。

      事务提供了一种“将多个命令打包,然后一次性、按顺序地执行”的机制,并且事务在执行的期间不会主动中断——服务器在执行完事务中的所有命令之后,才会继续处理其他客户端的其他 命令。 

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。

 

      1)开始事务

   MULTI 命令的执行标记着事务的开始:

   这个命令唯一做的就是,将客户端的 REDIS_MULTI 选项打开,让客户端从非事务状态切换到事 务状态

                   

  2)命令入队

 当客户端处于非事务状态下时,所有发送给服务器端的命令都会立即被服务器执行,但是,当客户端进入事务状态之后,服务器在收到来自客户端的命令时,不会立即执行命令, 而是将这些命令全部放进一个事务队列里,然后返回 QUEUED ,表示命令已入队,下面流程图: 

                           

事务队列是一个数组,每个数组项是都包含三个属性:

1. 要执行的命令(cmd)。

2. 命令的参数(argv)。

3. 参数的个数(argc)。

3)执行事务

               前面说到,当客户端进入事务状态之后,客户端发送的命令就会被放进事务队列里。 但其实并不是所有的命令都会被放进事务队列,其中的例外就是 EXEC 、DISCARD 、MULTI 和 WATCH 这四个命令——当这四个命令从客户端发送到服务器时,它们会像客户端处于非 事务状态一样,直接被服务器执行:

                      

如果客户端正处于事务状态,那么当 EXEC 命令执行时,服务器根据客户端所保存的事务队 列,以先进先出(FIFO)的方式执行事务队列中的命令:最先入队的命令最先执行,而最后入 队的命令最后执行。

4)在事务和非事务状态下执行命令

         无论在事务状态下,还是在非事务状态下,Redis 命令都由同一个函数执行,所以它们共享很 多服务器的一般设置,比如 AOF 的配置、RDB 的配置,以及内存限制,等等。 不过事务中的命令和普通命令在执行上还是有一点区别的,其中最重要的两点是:

        1. 非事务状态下的命令以单个命令为单位执行,前一个命令和后一个命令的客户端不一定 是同一个; 而事务状态则是以一个事务为单位,执行事务队列中的所有命令:除非当前事务执行完 毕,否则服务器不会中断事务,也不会执行其他客户端的其他命令。

         2. 在非事务状态下,执行命令所得的结果会立即被返回给客户端; 而事务则是将所有命令的结果集合到回复队列,再作为 EXEC 命令的结果返回给客户端。
 

5)事务状态下的 DISCARD 、MULTI 和 WATCH 命令

           除了 EXEC 之外,服务器在客户端处于事务状态时,不加入到事务队列而直接执行的另外三 个命令是 DISCARD 、MULTI WATCH 。
           DISCARD 命令用于取消一个事务,它清空客户端的整个事务队列,然后将客户端从事务状态 调整回非事务状态,最后返回字符串 OK 给客户端,说明事务已被取消。 Redis 的事务是不可嵌套的,当客户端已经处于事务状态,而客户端又再向服务器发送 MULTI 时,服务器只是简单地向客户端发送一个错误,然后继续等待其他命令的入队。MULTI 命令 的发送不会造成整个事务失败,也不会修改事务队列中已有的数据。

           WATCH 只能在客户端进入事务状态之前执行,在事务状态下发送 WATCH 命令会引发一个 错误,但它不会造成整个事务失败,也不会修改事务队列中已有的数据(和前面处理 MULTI 的情况一样)。
 

  • 事务的 ACID 性质
     

 Redis 事务保证了其中的一致性(C)和隔离性(I),但并不保证原子性(A)和持久性(D)。

          原子性(Atomicity)
          单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。 如果一个事务队列中的所有命令都被成功地执行,那么称这个事务执行成功。 另一方面,如果 Redis 服务器进程在执行事务的过程中被停止——比如接到 KILL 信号、宿主机器停机,等等,那么事务执行失败。 当事务失败时,Redis 也不会进行任何的重试或者回滚动作。

        一致性(Consistency)
       Redis 的一致性问题可以分为三部分来讨论:入队错误、执行错误、Redis 进程被终结

入队错误:
在命令入队的过程中,如果客户端向服务器发送了错误的命令,比如命令的参数数量 不对,等等,那么服务器将向客户端返回一个出错信息,并且将客户端的事务状态设为 REDIS_DIRTY_EXEC 。 当客户端执行 EXEC 命令时,Redis 会拒绝执行状态为 REDIS_DIRTY_EXEC 的事务,并返回失败信息

执行错误:
如果命令在事务执行的过程中发生错误,比如说,对一个不同类型的 key 执行了错误的操作, 那么 Redis 只会将错误包含在事务的结果中,这不会引起事务中断或整个失败,不会影响已执 行事务命令的结果,也不会影响后面要执行的事务命令,所以它对事务的一致性也没有影响。

Redis 进程被终结:

如果 Redis 服务器进程在执行事务的过程中被其他进程终结,或者被管理员强制杀死,那么根 据 Redis 所使用的持久化模式,可能有以下情况出现:

  • 内存模式:如果 Redis 没有采取任何持久化机制,那么重启之后的数据库总是空白的,所以数据总是一致的。
  • RDB 模式:在执行事务时,Redis 不会中断事务去执行保存 RDB 的工作,只有在事务执行之后,保存 RDB 的工作才有可能开始。所以当 RDB 模式下的 Redis 服务器进程在事务中途被杀死时,事务内执行的命令,不管成功了多少,都不会被保存到 RDB 文件里。恢复数据库需要使用现有的 RDB 文件,而这个 RDB 文件的数据保存的是最近一次的数据库快照(snapshot),所以它的数据可能不是最新的,但只要 RDB 文件本身没有因为其他问题而出错,那么还原后的数据库就是一致的。
  •  AOF 模式:因为保存 AOF 文件的工作在后台线程进行,所以即使是在事务执行的中途, 保存 AOF 文件的工作也可以继续进行,因此,根据事务语句是否被写入并保存到 AOF 文件,有以下两种情况发生:

        1)如果事务语句未写入到 AOF 文件,或 AOF 未被 SYNC 调用保存到磁盘,那么当进 程被杀死之后,Redis 可以根据最近一次成功保存到磁盘的 AOF 文件来还原数据库,只 要 AOF 文件本身没有因为其他问题而出错,那么还原后的数据库总是一致的,但其中的数据不一定是最新的。

        2)如果事务的部分语句被写入到 AOF 文件,并且 AOF 文件被成功保存,那么不完整的事务执行信息就会遗留在 AOF 文件里,当重启 Redis 时,程序会检测到 AOF文件并不 完整,Redis 会退出,并报告错误。需要使用 redis-check-aof 工具将部分成功的事务命令移除之后,才能再次启动服务器。还原之后的数据总是一致的,而且数据也是最新的(直到事务执行之前为止)

        隔离性(Isolation)
         Redis 是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执 行完所有事务队列中的命令为止。因此,Redis 的事务是总是带有隔离性的。

        持久性(Durability)

        因为事务不过是用队列包裹起了一组 Redis 命令,并没有提供任何额外的持久性功能,所以事务的持久性由 Redis 所使用的持久化模式决定:

  • 在单纯的内存模式下,事务肯定是不持久的。
  • 在RDB模式下,服务器可能在事务执行之后、RDB文件更新之前的这段时间失败,所以RDB 模式下的 Redis 事务也是不持久的。
  • 在 AOF 的“总是 SYNC ”模式下,事务的每条命令在执行成功之后,都会立即调用 fsync 或 fdatasync 将事务数据写入到 AOF 文件。但是,这种保存是由后台线程进行的,主线程不会阻塞直到保存成功,所以从命令执行成功到数据保存到硬盘之间,还是有一段非常小的间隔,所以这种模式下的事务也是不持久的。

订阅与发布
 

         Redis 通过 PUBLISH 、SUBSCRIBE 等命令实现了订阅与发布模式,这个功能提供两种信息机制,分别是订阅/发布到频道和订阅/发布到模式,下文先讨论订阅/发布到频道的实现,再讨 论订阅/发布到模式的实现

        作为例子,下图展示了频道 channel1 ,以及订阅这个频道的三个客户端——client2 、 client5 和 client1 之间的关系:

                                             

当有新消息通过 PUBLISH 命令发送给频道 channel1 时,这个消息就会被发送给订阅它的三个客户端:

                                    

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

尚硅谷是一个教育机构,他们提供了一份关于Redis学习笔记。根据提供的引用内容,我们可以了解到他们提到了一些关于Redis配置和使用的内容。 首先,在引用中提到了通过执行命令"vi /redis-6.2.6/redis.conf"来编辑Redis配置文件。这个命令可以让你进入只读模式来查询"daemonize"配置项的位置。 在引用中提到了Redis会根据键值计算出应该送往的插槽,并且如果不是该客户端对应服务器的插槽,Redis会报错并告知应该前往的Redis实例的地址和端口。 在引用中提到了通过修改Redis的配置文件来指定Redis的日志文件位置。可以使用命令"sudo vim /etc/redis.conf"来编辑Redis的配置文件,并且在文件中指定日志文件的位置。 通过这些引用内容,我们可以得出结论,尚硅谷的Redis学习笔记涵盖了关于Redis的配置和使用的内容,并提供了一些相关的命令和操作示例。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Redis学习笔记--尚硅谷](https://blog.csdn.net/HHCS231/article/details/123637379)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Redis学习笔记——尚硅谷](https://blog.csdn.net/qq_48092631/article/details/129662119)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值