redis开发与运维笔记(1)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chenpeng19910926/article/details/82903704

1、Redis特性与优点

  • 速度快。redis所有数据都存放于内存;是用C语言实现,更加贴近硬件;使用了单线程架构,避免了多线程竞争问题。Redis使用了单线程架构和IO多路复用模型(epoll作为多路复用技术的实现,非阻塞IO)来实现。每次客户端的请求都会经过发送命令、执行命令、返回结果三个阶段。所有客户端命令都会放入到同一个队列中,然后逐个被执行。单线程避免了线程切换和竞态产生的消耗
  • 基于键值对的数据结构,支持的数据结构丰富。它主要提供了5种数据结构: 字符串、 哈希、 列表、 集合、 有序集合, 同时在字符串的基础之上演变出了位图(Bitmaps) 和HyperLogLog两种神奇的“数据结构”, 并且随着LBS(Location Based Service, 基于位置服务) 的不断发展, Redis3.2版本中加入有关GEO(地理信息定位) 的功能。每种数据结构都有底层的内部编码实现,而且是多种实现,redis会在合适的场景下选择合适的内部编码。
  • 功能丰富。键过期功能,用来实现缓存;提供了发布订阅功能,实现消息系统支持Lua脚本提供简单的事务功能;提供了Pipeline,一次性将一批命令传给redis服务器,减小了网络开销
  • 简单,稳定。源码少,3.0版本源代码只有5w行左右
  • 客户端语言多。
  • 持久化。两种持久化方式: RDB和AOF
  • 主从复制。复制功能是分布式Redis的基础
  • 高可用和分布式。2.8版本提供了高可用实现Redis Sentinel, 它能够保证Redis节点的故障发现和故障自动转移。 Redis从3.0版本正式提供了分布式实现Redis Cluster, 它是Redis真正的分布式实现, 提供了高用、 读写和容量的扩展性。

2、Redis启动与关闭

  • 服务端启动。配置文件启动,redis-server  /opt/redis/redis.conf
  • 客户端启动。redis-cli -h 127.0.0.1  -p 6379
  • 停止redis服务。redis-cli shutdown nosave|save  关闭过程:断开与客户端的连接;持久化文件生成。不建议kill -9 暴力杀进程,极端下会造成丢失数据的情况

3、Redis的常用API

  • 查看所有键。【keys *】会遍历所有键,禁用
  • 键总数。【dbsize】不会遍历所有键,直接获取redis内置的键总数
  • 检查键是否存在。【exists key】存在返回1,不存在返回0
  • 删除键。【del key】返回结果为成功删除的键的个数
  • 设置键过期。【expire key seconds】秒级别;【expireat key timestamp 】秒级时间戳;【pexpire key milliseconds】毫秒级过期 ;【pexpireat key milliseconds-timestamp 】毫秒级时间戳
  • 检查键过期。【ttl key】返回键的剩余过期时间,秒级;【pttl key】毫秒级;-1,键没设置过期时间;-2 键不存在
  • 清除过期时间。【persist】;对于字符串类型键,执行set命令也会去掉过期时间;setex命令作为set+expire的组合, 不但是原子执行, 同时减少了一次网络通讯的时间
  • 查看键的类型。【type key】键不存在,返回none
  • 键重命名。rename key newkey。如果在rename newkey之前,newkey已经存在,newkey的值会被覆盖。防止被覆盖,提供了renamenx命令。重命名期间会删除原来的key,如果key对应的值过大,存在阻塞redis的可能
  • 随机返回一个键。randomkey。

4、Redis的字符串

内部编码,有三种

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

应用场景

  • 缓存
  • 计数
  • 共享session
  • 限速。每个用户的请求频率,每个ip的请求频率

命令

  • 设置值。set key value [ex seconds] [px milliseconds] [nx|xx]。其中setnx可以作为分布式锁的实现
  • 获取值。 get key。不存在返回 nil(空)
  • 批量设置值,mset key value [key value ...] ;批量获取值,mget key [key ...] 。一次请求的网络时间大于命令处理时间。学会使用批量操作,能减少大量的网络消耗。提高业务处理效率。但是一次批量操作过多,有可能导致Redis阻塞或者网络拥堵
  • 计数。incr、decr、incrby、decrby、incrbyfloat。很多其他的语言和存储系统通过cas实现计数,会有一定的cpu开销。redis单线程模型,完全不存在这个问题。
  • 追加值。append key value
  • 字符串长度。strlen key。每个中文占用三个字节,也就是三个长度
  • 设置并返回原值。getset key value
  • 设置指定位置的字符。setrange key offset value
  • 获取部分字符串。getrange key start end。时间复杂度O(n)

5、Redis的HASH结构

内部编码

  • ziplist(压缩列表)。当哈希类型元素个数小于hash-max-ziplist-entries
    配置(默认512个) 、 同时所有值都小于hash-max-ziplist-value配置(默认64
    字节) 时, Redis会使用ziplist作为哈希的内部实现, ziplist使用更加紧凑的
    结构实现多个元素的连续存储, 所以在节省内存方面比hashtable更加优秀 
  • hashtable(哈希表)。当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现

命令

  • 设置field值。hset key field value。hsetnx,和setnx作用相同,只不过作用域由键变为field
  • 获取field值。hget key field。如果field不存在,返回nil
  • 删除field。hdel key field [field ...] 
  • 计算field个数。hlen key
  • 批量设置和获取field-value。hmget key field [field ...] ;hmset key field value [field value ...] 。
  • 判断field是否存在。hexists key field。存在返回1,不存在返回0
  • 获取所有field。hkeys key
  • 获取所有value。hvals key
  • 获取所有field-value。hgetall key。如果获取的元素比较多,可能会阻塞Redis。
  • hincrby key field;hincrbyfloat key field 
  • 计算value的字符串长度。hstrlen key field

7、Redis的列表结构

列表中的每个字符串称为元素(element),一个列表最多存储2^32-1个元素。可以充当栈和队列,比较灵活。列表中的元素是有序的且可重复的,可以通过下标获取某个元素

内部编码

  • ziplist(压缩列表)。当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置时(默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使用
  • linkedlist(链表):当列表类型无法满足ziplist的条件时, Redis会使用linkedlist作为列表的内部实现。
  • Redis3.2版本提供了quicklist内部编码,简单地说它是以一个ziplist为节点的linkedlist,它结合了ziplist和linkedlist两者的优势,为列表类型提供了一种更为优秀的内部编码实现

应用场景

  • 消息队列。Redis的lpush+brpop命令组合即可实现阻塞队列, 生产者客户端使用lrpush从列表左侧插入元素, 多个消费者客户端使用brpop命令阻塞式的“抢”列表尾部的元素, 多个客户端保证了消费的负载均衡和高可用性。
  • 文章列表。哈希存储每篇文章的详细信息。列表存储每个人的文章列表。支持分页获取,如果列表较大,获取列表中间元素的性能会变差,可以使用redis3.2版本的quicklist内部编码实现。
  • lpush+lpop=Stack(栈) ;lpush+rpop=Queue(队列) ;lpush+brpop=Message Queue(消息队列,阻塞队列); lpush+ltrim=Capped Collection(有限集合) 

命令

  • 添加操作。从右边插入数据 rpush key value [value ...];从左边插入数据  lpush key value [value ...];向某个元素前或后插入数据 linsert key before|after pivot value
  • 查找。获取指定范围的元素列表 lrange key start end(包含end);获取指定下标的元素 lindex key index(-1为最后一个元素);获取列表长度 llen key
  • 删除。从左侧弹出元素 lpop key;从右侧弹出元素 rpop key;删除指定元素 lrem key count value(count>0 从左到右,删除最多count个元素;count<0 从右到左;count=0,删除所有);按照索引范围修剪列表 ltrim key start end
  • 修改。修改执行索引下标的元素 lset key index newValue;
  • 阻塞操作。blpop key [key ...] timeout ;brpop key [key ...] timeout 。需要注意两点:第一点,如果blpop多个key,一旦有一个键能弹出元素,立刻给客户端返回;第二点,如果多个客户端对同一个key执行blpop,那么最先执行blpop的客户端可以获取到弹出的值。

8、Redis的Set

不允许有重复元素,无序,不能通过索引下标获取元素。一个集合最多可以存储2^32-1个元素。支持集合内的增删改查,集合的交集、并集、差集。

内部编码

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

使用场景

  • 标签(tag)。使用sinter命令计算用户的共同兴趣。
  • 生成随机数,抽奖

命令。集合内操作。

  • 添加元素。sadd key element [element ...]
  • 删除元素。srem key element [element ...] 
  • 计算元素个数。scard key 。时间复杂度O(1),不会遍历集合。
  • 判断元素是否在集合中。sismember key element 。在集合内返回1,不在返回0
  • 随机从集合中返回指定个数元素。srandmember key [count] 
  • 从集合随机弹出指定个数的元素。spop key  [count] 
  • 获取所有元素。smembers key 。如果元素过多,存在阻塞redis的可能。可以用sscan来完成

(2)命令,集合间操作。

  • 求多个集合的交集。sinter key [key ...] 
  • 求多个集合的并集。suinon key [key ...] 
  • 求多个集合的差集。sdiff key [key ...] 
  • 将集合操作的结果保存。sinterstore/suionstore/sdiffstore  destination key [key ...] 

9、Redis的有序set

内部编码

  • ziplist(压缩列表) : 当有序集合的元素个数小于zset-max-ziplistentries配置(默认128个) , 同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节) 时, Redis会用ziplist来作为有序集合的内部实现, ziplist
    可以有效减少内存的使用 
  • skiplist(跳跃表) : 当ziplist条件不满足时, 有序集合会使用skiplist作为内部实现, 因为此时ziplist的读写效率会下降。

使用场景

  • 排行榜

命令。集合内的命令。

  • 添加成员。zadd key score member [score member ...] 

    ·Redis3.2为zadd命令添加了nx、 xx、 ch、 incr四个选项:
    ·nx: member必须不存在, 才可以设置成功, 用于添加。
    ·xx: member必须存在, 才可以设置成功, 用于更新。
    ·ch: 返回此次操作后, 有序集合元素和分数发生变化的个数
    ·incr: 对score做增加, 相当于后面介绍的zincrby。

  • 计算成员个数。zcard key 
  • 计算某个成员的分数。zscore key member 
  • 计算成员排名。zrank key member (分数由低到高);zrevrank key member (分数由高到低)
  • 删除成员。zrem key member [member ...] 
  • 增加成员分数。zincrby key increment member 
  • 返回指定排名范围的成员。zrange key start end [withscores] (排名由低到高);zrevrange key start end [withscores] (排名由高到低)
  • 返回指定分数范围的成员。zrangebyscore key min max [withscores] [limit offset count] 。其中zrangebyscore按照分数从低到高返回, zrevrangebyscore反之。 例如
    下面操作从低到高返回200到221分的成员, withscores选项会同时返回每个
    成员的分数。 [limit offset count]选项可以限制输出的起始位置和个数 。同时min和max还支持开区间(小括号) 和闭区间(中括号) , -inf和
    +inf分别代表无限小和无限大。
  • 返回指定分数范围成员个数。zcount key min max 
  • 删除指定排名内的升序元素。zremrangebyrank key start end 
  • 删除指定分数范围的成员。zremrangebyscore key min max 

命令,集合间的操作

  • 交集。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 
  • 并集。zunionstore destination numkeys key [key ...] [weights weight [weight ...]][aggregate sum|min|max] 。

10、Redis 的Bitmaps

(1)概述。Bitmaps本身的数据结构就是字符串,支持对字符串的位进行操作。

(2)每个独立用户是否访问过网站存放在Bitmaps中,将访问的用户记做1,没有访问的用户记做0,用偏移量作为用户的id

  • 设置值。setbit key offset value 。初始化的时候,如果偏移量非常大,整个初始化过程会非常慢,可能会造成redis阻塞
  • 获取值。gitbit key offset 。返回0说明没有访问过
  • 获取Bitmaps指定范围值为1的个数 。bitcount [start][end] 。
  • Bitmaps间的运算 。bitop op destkey key[key....] 。做多个Bitmaps的and(交集) 、 or(并集) 、 not(非) 、 xor(异或) 操作并将结果保存在destkey中
  • 计算Bitmaps中第一个值为targetBit的偏移量。bitpos key targetBit [start] [end]

(3)Bitmaps分析

   假设网站有1亿用户, 每天独立访问的用户有5千万, 如果每天用集合类型和Bitmaps分别存储活跃用户。
   集合类型内存量:64位*50000000=400M。
   Bitmaps内存量:1位*50000000=12.5M。

11、Redis 的HyperLogLog

  • Redis中hyperloglog是用来做基数统计的,其优点是:在输入元素的数量或者体积非常非常大的时候,计算基数所需的空间总是固定的,并且是很小的。在Redis里面,每个Hyperloglog键只需要12Kb的大小就能计算接近2^64个不同元素的基数,但是hyperloglog只会根据输入元素来计算基数,而不会存储元素本身,所以不能像集合那样返回各个元素本身
  • pfadd key element [element …]。添加操作。如果添加成功返回1
  • pfcount key [key …]。求一个或多个key的基数,计算独立用户数
  • pfmerge destkey sourcekey [sourcekey ...]。合并。pfmerge可以求出多个HyperLogLog的并集并赋值给destkey
  • HyperLogLog内存占用量小得惊人, 但是用如此小空间来估算如此巨大的数据, 必然不是100%的正确, 其中一定存在误差率。 Redis官方给出的数字是0.81%的失误率

12、GEO

  • 增加地理位置信息。geoadd key longitude latitude member [longitude latitude member ...]。longitude、 latitude、 member分别是该地理位置的经度、 纬度、 成员。添加和更新都是用此命令,可以同时添加多个地理位置信息。
  • 获取地理位置信息。geopos key member [member ...]
  • 获取两个地址位置的距离。geodist key member1 member2 [unit]。unit代表返回结果的单位,m(meters) 代表米、km(kilometers) 代表公里、mi(miles) 代表英里、ft(feet) 代表尺
  • 获取指定位置范围内的地理信息位置集合。georadius key longitude latitude/georadiusbymember key member radiusm|km|ft|mi [withcoord] [withdist][withhash] [COUNT count] [asc|desc] [store key] [storedist key]
    都是以一个地理位置为中心算出指定半径内的其他地理信息位置

  • 获取geohash。geohash key member [member ...]。Redis使用geohash将二维经纬度转换为一维字符串。
    GEO的数据类型为zset, Redis将所有地理位置信息的geohash存放在zset中字符串越长, 表示的位置更精确, 例如geohash长度为9时, 精度在2米左右两个字符串越相似, 它们之间的距离越近, Redis利用字符串前缀匹配算法实现相关的命令
    geohash编码和经纬度是可以相互转换的

  • 删除地理位置信息。zrem key member。GEO没有提供删除成员的命令, 但是因为GEO的底层实现是zset, 所以可以借用zrem命令实现对地理位置信息的删除。

猜你喜欢

转载自blog.csdn.net/chenpeng19910926/article/details/82903704