Fork me on GitHub

redis入门学习笔记

mark

启动关闭reids

启动redis-server

  • $ redis-server 默认配置启动(6379端口)
  • $ redis-server –port 6666 运行配置,可以修改端口等配置
  • $ redis-server /usr/local/bin/redis.conf 将配置写到配置文件中再启动(生产环境中常用)

daemonize yes表示以守护进程的方式启动redis(放置在后台运行,关闭远程连接不中断)

启动redis-cli

  • $redis-cli -h 127.0.0.1 -p 6666 -a xdwizzno1 如果没有-h默认127.0.0.1,如果没有-p默认6379
  • $redis-cli -h 127.0.0.1 -p 6666 get name 直接取回命令返回结果

将密码写入命令行会弹出警告Warning: Using a password with ‘-a’ or ‘-u’ option on the command line interface may not be safe.

停止redis服务

$redis-cli shutdown nosave|save

不要用kill直接杀掉,不但不会做持久化操作,而且缓冲区等资源不能被优雅地关闭,极端情况下可能会造成数据丢失

如果报错(error) ERR Errors trying to SHUTDOWN. Check logs.可能是权限问题

如果在客户端里面,可以用exit退出

redis默认只允许本机访问,修改配置文件中#bind 127.0.0.1 为bind 0.0.0.0并重启即可远程访问

(error) NOAUTH Authentication required.报错表示出现了认证问题,输入auth xdwizzno1(密码)即可

Could not connect to Redis at 127.0.0.1:6666: Connection refused错误表示还未开启redis-server或者开启失败

redis高性能三大因素

  • 纯内存存储
  • IO多路复用
  • 单线程架构

全局命令

  • keys * 查看所有键
  • dbsize 查看当前数据库键总数,dbsize不会遍历所有键,而是直接获取redis内置键总数变量,时间复杂度为O(1),而keys * 会遍历所有键,当redis保存了大量键时,线上环境禁止使用
  • exists key 检查键是否存在
  • del key 删除键,对所有数据结构类型适用
  • expire key seconds 设置键过期时间,过期后自动删除
  • ttl key 查看键剩余过期时间,-1表示没有设置,-2表示键不存在
  • type key 查看键的数据结构类型,不存在则返回none
  • rename key newkey 如果newkey已经存在,则会覆盖
  • renamenx key newkey
  • randomkey 随机返回一个键

redis每种数据结构都有两种以上内部编码实现,可以用object encoding key来查询

redis是单线程

字符串

命令

  • setex key second value 设置秒级过期时间
  • setnx key value 键必须不存在才能设置成功(若多个客户端同时执行,只有一个客户端能设置成功,可作为分布式锁的实现方案)
  • set key value xx 键必须存在才能设置成功
  • mset 批量设置值
  • mget 批量获取值,只需要1次网络时间,比n次get高效
  • incr key 对值自增,值不是整数返回(error) ERR value is not an integer or out of range,key不存在则创建key初始化为0并自增为1
  • decr自减,incrby自增指定数字,incrbyfloat自增浮点数,decr同理
  • append key value 向字符串尾部追加值
  • strlen key 查询字符串长度
  • getset key value 设置并返回原值
  • setrange key offset value 设置指定位置字符(从0开始)
  • getrange key start end 获取部分字符串,偏移量均从0开始

字符串三种内部编码

  • int 8个字节的长整型
  • embstr 小于等于39字节的字符串
  • raw 大于39字节的字符串

典型应用场景

  • 缓存
  • 计数
  • 共享session
  • 限速

看《Redis开发与运维》上的伪码

哈希

键值对本身又是另一个键值对结构

命令

  • hset key field value
  • hsetnx key field value
  • hget key field
  • hdel key field
  • hlen key 计数field个数
  • hmget key field [field …]
  • hmset key field [field value …]
  • hexists key field
  • hkeys key 获取所有field
  • hvals key 获取所有value
  • hgetall key 获取所有field-value
  • hincrby key field increment
  • hincrbyfloat key field increment (没有hincr)
  • hstrlen key field 计数value的字符串长度

内部编码

  • ziplist 压缩列表,当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512个)、同时所有值都小于hash-max-ziplist-value配置(默认64字节)时使用,更节省内存
  • hashtable 哈希表,无法满足ziplist条件时使用,因为此时ziplist读写效率会下降,而hashtable读写时间复杂度为O(1)

缓存用户信息的方式

原生字符串方式

每个属性一个键

优点:简单直观,每个属性都支持更新操作

缺点:占用过多的键,内存占用大,用户信息内聚性差,一般不在生产环境使用

序列化字符串方式

将用户信息序列化后用一个键保存

优点:简化编程,如果合理使用序列化可以提高内存使用效率

缺点:序列化与反序列化有一定开销,每次更新属性都要把全部数据取出并反序列化,更新后再序列化到redis中

哈希方式

每个用户属性使用一对field-value,但只用一个键保存

优点:简单直观,如果使用合理可以减少内存空间的使用

缺点:要控制ziplist与hashtable两种内部编码的转换,hashtable会消耗更多内存

列表

用来存储多个有序字符串
特点:

  • 列表中元素有序
  • 元素可以重复

命令

  • rpush key value [value …] 从右边插入元素
  • lpush key value [value …] 从左边插入元素
  • linsert key before|after pivot value 在列表中从左向右查找第一个等于pivot的元素,并在其前|后插入一个新的元素value(如果不存在等于pivot的元素,则插入失败,返回-1)
  • lrange key start end 从左向右获取指定索引范围内的所有元素,索引下标从左到右分别是0到N-1,从右到左分别是-1到-N,且end选项包含自身
  • lindex key index 获取列表指定索引下标的元素
  • llen key 获取列表长度
  • lpop key 从列表左侧弹出元素
  • rpop key 从列表右侧弹出元素
  • lrem key count value 找到等于value的元素进行删除,当count大于0时,从左至右删除最多count个元素,当count小于0时,从右至左删除最多count绝对值个元素,当count等于0时,全部删除
  • ltrim key start end 只保留索引内的元素
  • lset key index newValue 修改指定下标的元素
  • blpop(brpop) key [key …] timeout 阻塞式弹出,若列表不为空,客户端立即返回,若列表为空,则客户端在timeout秒后返回,timeout等于0时会一直阻塞下去,如果在此期间另一个客户端向某列表添加了数据,则客户端立即返回

阻塞式弹出注意:

  • 如果是多个键,则brpop从左向右遍历所有键,一旦有一个键能够弹出元素,则客户端立即返回
  • 如果多个客户端对同一个键执行brpop。那么最先执行brpop命令的客户端可以获取到弹出的值并弹出

内部编码

  • ziplist 压缩列表,当列表中的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置时(默认64字节),redis选择ziplist作为列表内部实现来减少内存的使用
  • linkedlist 链表,当列表类型无法满足ziplist的条件时,reids会使用linkedlist作为列表的内部实现
  • quicklist redis3.2提供,结合了上述两者的优势

典型应用场景

  • 文章列表 文章使用哈希或者序列化为字符串存储
  • 消息队列 lpush+brpop
  • 栈 lpush+lpop
  • 队列 lpush+rpop
  • 有限集合 lpush+ltrim

集合

不允许有重复元素,元素无序,不能通过索引获取

集合内操作

  • sadd key element [element …] 添加元素
  • srem key element [element …] 删除元素
  • scard key 计算元素个数,直接使用redis内部变量,不会遍历所有元素,时间复杂度O(1)
  • sismember key element 判断元素是否在集合中
  • srandmemeber key [count] 随机从集合中返回指定个数元素,不写count默认为1
  • spop key [count] 从集合中随机弹出指定个数元素,不写默认为1
  • smembers key 获取所有元素

集合间操作

  • sinter key [key …] 求多个集合交集
  • sunion key [key …] 求多个集合并集
  • sdiff key [key …] 求多个集合差集,前面的key对应的集合减后面的key对应的集合
  • sinterstore destination key [key …]
  • sunionstore destination key [key …]
  • sdiffstore destination key [key …] 上述三条命令将交集、并集、差集结果保存到集合destinaion中

内部编码

  • intset 整数集合,当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认512个)时,redis默认选用intset来作为set的内部实现,从而减少内存使用
  • hashtable 哈希表,无法满足上述条件时使用

典型应用场景

  • sadd 给用户添加标签,给标签添加用户
  • sadd+sinter 社交需求
  • spop/srandmember 生成随机数,如抽奖等

有序集合

不能有重复元素,可以排序,用score作为排序依据,score可以重复

集合内操作

  • zadd key score member [score member …] 添加成员
  • zadd key nx … 必须不存在才能添加成功
  • zadd key xx … 必须存在才能添加成功
  • zadd key ch … 返回此次操作后集合元素和分数发生变化的个数
  • zadd key incr … 增加score
  • zcard key 计算成员个数
  • zscore key member 计算某个成员分数
  • zrank/zrevrank key member 从低到高/从高到低计算成员的排名(排名从0开始计算)
  • zrem key member 删除成员
  • zincrby key increment member 增加成员的分数
  • zrange/zrevrange key start end [withscores] 从低到高/从高到低返回指定排名范围内的成员,加上withscores同时返回成员分数
  • zrangebyscore/zrevrangebyscore key min max [withscores] [limit offset count] 从低到高/从高到低返回指定分数范围内的成员,加上withscores同时返回成员分数,limit offset count可以限制输出的起始位置和个数(起始位置0是相当于满足要求的成员,而不是整个zset),min与max支持开区间(小括号)和闭区间(中括号),-inf和+inf分别表示无穷小和无穷大
  • zcount key min max 返回指定分数范围内成员个数
  • zremrangebyrank key start end 删除升序排名中指定位置的元素
  • zrangebyscore key min max 删除指定分数范围内的元素

集合间操作

1.交集

zinterstore destination numkeys key [key …] [weights weight [weight …]] [aggregate sum|min|max]

  • destination 交集计算结果保存到这个键
  • numkeys 需要做交集计算键的个数
  • key [key …] 需要做交集计算的键
  • [weights weight [weight …]] 每个键的权重,做交集计算时,每个键中的每个member会将自己的分数乘以这个权重,每个键的权重默认为1
  • [aggregate sum|min|max] 计算成员交集后,分值可以按照sum、min、max做汇总,默认值是sum(意思是取交集后元素的新值是取交集前每个集合中该元素的值乘以权重后的和、最小值还是最大值)

2.并集

zunionstore destination numkeys key [key …] [weights weight [weight …]] [aggregate sum|min|max]

参数与交集一致,只有两个集合中都存在的元素才使用sum、min或者max,只存在于一个集合中的元素的值直接乘以权重保存到destination中

内部编码

  • ziplist 压缩列表,当有序集合中的元素个数小于zset-max-ziplist-entries配置(默认128个),同时列表中每个元素的值都小于zset-max-ziplist-value配置时(默认64字节),redis选择ziplist作为有序集合内部实现来减少内存的使用
  • skiplist 跳跃表,无法满足上述条件时使用,因为此时ziplist读写效率下降

典型应用场景

  • 排行榜系统
  • 点赞系统

键过期

  • expire key seconds 键在seconds秒后过期
  • expireat key timestamp 键在秒级时间戳timestamp后过期
  • pexpire key milliseconds 键在milliseconds毫秒后过期
  • pexpireat key milloseconds-timestamp 键在毫秒级时间戳timestamp后过期
  • ttl key 查看秒级键剩余过期时间
  • pttl key 查看毫秒级键剩余过期时间
  • presist key 将键的过期时间删除
  • 如果过期时间为负值,则键会立即被删除
  • 对于字符串类型键,执行set命令会去掉过期时间
  • redis不支持二级数据结构内部元素的过期功能
  • setex命令作为set+expire的组合,不但是原子执行,同时减少了一次网络通讯时间

键迁移

  1. move key db 用于在redis内部多个数据库间进行数据迁移,不建议在生产环境使用
  2. dump+restore 不同redis实例间进行数据迁移,非原子性,不支持多个键
  3. migrate host port key|”” destination-db timeout [copy] [replace] [keys key [key …]] 原子执行
  • host 目标redis的IP地址
  • port 目标redis的端口
  • key|”” 如果只迁移一个键就写在这,如果迁移多个键这里写””,具体的键写在最后
  • destination-db 目标redis的数据库索引(哪一个数据库)
  • timeout 迁移的超时时间,单位毫秒
  • [copy] 添加后不会删除源键
  • [replace] 添加后migrate不管目标redis是否存在该键都会正常迁移进行数据覆盖
  • [keys key [key …]] 要迁移的多个键
  • 不能迁移到被密码保护的目标redis上

遍历键

全量遍历键

keys pattern 通过正则表达式查询keys

  • *表示匹配任意字符
  • ?表示匹配一个字符
  • []表示匹配部分字符,如[r,j]*匹配以r或者j开头的key
  • \x用来做转义匹配特殊字符

linux中批量删除部分keys:
不进入redis客户端,执行redis-cli -p 6666 -a xdwizzno1 keys *edis | xargs redis-cli -p 6666 -a xdwizzno1 del 其中keys后为自定义查询条件

如果redis包含大量的键,执行keys可能造成redis阻塞,一般不要在生产环境使用keys

渐进式遍历

scan cursor [match pattern] [count number]

  • cursor 游标,第一次遍历从0开始,游标为0表示遍历结束
  • match pattern 模式匹配
  • count number 每次遍历的键个数,默认10

每次执行时间复杂度为O(1),但需要多次执行才能完全遍历
hgetall、smembers、zrange分别可以用hscan、sscan、zscan代替

数据库管理

  • select dbIndex 切换数据库,不同数据库之间是隔离的
  • flushdb 清除当前数据库
  • flushall 清除所有数据库

上述两个命令不仅会将所有数据清除,而且如果键值较多,存在阻塞redis的可能性,慎用

一般只用0号数据库,如果需要使用多个数据库可以在一台机器上部署多个redis实例

-------------本文结束感谢您的阅读-------------
undefined