redis踩坑笔记

最近开始拜读付磊的redis开发与运维一书,作为起点正式地开始接触redis,这篇博客记录一下笔记

第一章

1. redis使用场景

1) 缓存

在大型网站中使用,之前在公司也一直有听到使用redis作为缓存来降低后端数据源的压力,不过购物车和下单线业务都不需要缓存所以在工作中一直都没有用上,残念

2)排行榜系统

应该说是按照复杂维度计算出的排行榜,大学的时候做过数独游戏的排行榜,当时做的demo为了应付老师实在是太简陋,如果更新到现在应该会用上redis吧(笑)

3)计数器应用

第一个反应是小破站每个视频的播放量,公司app上商品的浏览数,保证数据的实时性

4)社交网络

社交网络访问量确实大,微博都常崩

5)消息队列系统

消息队列拥有业务解耦/非实时业务削峰/异步处理/日志处理特性

2. 安装redis

书上推荐的方法是源码的方式安装3.0.7版本:

wget http://download.redis.io/releases/redis-3.0.7.tar.gz

tar xzf redis-3.0.7.tar.gz

ln -s redis-3.0.7 redis

cd redis

make

make test

make install

注意:

make编译前要先安装好g++

3. 启动服务

启动服务端:

redis-server

打开后发现不能操作了,应该要放到后台运行,找到redis.conf 并修改 daemonize no 为 daemonize yes ,这样就可以默认启动就后台运行

~/redis-3.0.7$ redis-server redis.conf

启动客户端(两种方式):

zinan_ji@Jzn:~/redis-3.0.7$ redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"

zinan_ji@Jzn:~/redis-3.0.7$ redis-cli -h 127.0.0.1 -p 6379 get hello
"world"

4. 停止服务

zinan_ji@Jzn:~/redis-3.0.7$ redis-cli shutdown

第二章.API的理解和使用

1.预备

1.1 全局命令

1) 查看所有命令 keys * 

插入键值对用set set hello world hello是key,world是value

keys *会将所有的键输出

2)键总数dbsize

插入列表类型的键值对(值为多个元素组成)

127.0.0.1:6379> rpush mylist a b c d e f g
(integer) 7

dbsize会返回当前数据库键的总数。

127.0.0.1:6379> dbsize
(integer) 4
注意:dbsize直接获取的是一个总数变量,所以时间复杂度为O(1),keys会遍历所有键,所以复杂度是O(n),线上环境应该禁止使用,如果redis存储了大量键的时候。

3)检查键是否存在

exists keyname

存在返回1,不存在返回 0

127.0.0.1:6379> exists hello
(integer) 1
127.0.0.1:6379> exists helloworld
(integer) 0

4) 删除键 del key[key...]

del命令是通用命令什么数据结构类型都能删

成功返回删除key的个数,删除不存在的key则返回0

127.0.0.1:6379> del java
(integer) 1
127.0.0.1:6379> del mylist
(integer) 1
127.0.0.1:6379> exists java
(integer) 0
127.0.0.1:6379> exists mylist
(integer) 0
127.0.0.1:6379> del java
(integer) 1
127.0.0.1:6379> del mylist
(integer) 1
127.0.0.1:6379> exists java
(integer) 0
127.0.0.1:6379> exists mylist
(integer) 0
5) 键过期

expire key seconds 对键添加过期时间

ttl key 可以观察键的剩余过期时间(返回值-1是键没有设置过期时间,-2是键不存在)

6) 键的数据结构类型 type key

键不存在返回none

1.2  redis 对外支持stirng /list/set/zset/hash五种数据结构。每种都有自己底层的内部编码实现。

可以通过object encoding查询内部编码

每种数据结构都有两种以上的内部编码实现,redis会在合适的场景选择合适的内部编码。

好处: 方便改建和适应不同场景。

1.3 单线程架构

单线程架构和I/O多路复用模型来实现高性能的内存数据库服务

单线程避免了并发问题,客户端的命令都会进入到队列中逐个执行,但是每次只能有一个命令被执行

为什么还这么快?

1. 纯内存访问

2. 非阻塞I/O 

redis 使用epoll作为I/O多路复用技术的实现,再加上redis自身的事件处理模型将epoll中的连接/读写/关闭都转换为事件,不会在网络I/O上浪费过多时间

3. 避免了线程切换和竞态产生的消耗

单线程还有好处:

1. 简化数据结构和算法实现

2. 避免了线程切换和竞态产生的消耗

但是有问题就是,对每个命令的执行时间是有要求的,命令过长会导致其他命令阻塞,所以redis是面向快速执行场景的数据库。

2 字符串

最基础的数据结构,value可以是字符串/数字/二进制。但是值最大不能超过512MB

2.1 命令

1)设置值set key value [ex seconds] [px milliseconds] [nx|xx]

nx:键必须不存在,用作添加

xx:值必须存在,用作更新

setex key seconds value

setnx key value

setnx是作为分布式锁的一种实现方式。单线程下多个客户端执行setnx只有一个客户端能设置成功

2)获取值get key

3)批量设置值 mset key value key value...

4) 批量获取值 mget key key...

5) 计数 incr key 用于对值自增

还有自减decr/自增指定数字incrby/自减指定数字decrby/自增浮点数incrbyfloat

6)不常用命令

append key value 字符串末尾追加值

strlen key 字符串值长度

getset key value 设置并返回原值

setrange key offset value 设置指定位置的字符

getrange key start end 获取部分字符串

2.2 内部编码

int/embstr/raw分别为8字节长整型,小于等于39字节字符串,大于39字节的字符串

2.3 使用场景

1)缓存

2)计数

3)共享session

4)限速(限制每分钟获取短信验证码的频率,或者限制ip访问次数

记录手机号和incr计数实现

3 哈希

key,value={{field,value},{field,value}...}

3.1 命令

设值hset key field value
获取值hget key field
删除fieldhdel key field [field...]
计算field个数hlen key
批量设置或获取field-value

hmset key field value [field value...]

hmget key field [field...]

判断field是否存在hexists key field
获取所有fieldhkeys key
获取所有valuehvals key
获取所有的field-valuehgetall key/ hscan key
自增

hincrby key field

hincrbyfloat key field

计算value的字符串长度hstrlen key field
  

3.2 内部编码

ziplist:哈希类型元素个数小于hash-max-ziplist-entries配置(默认512)个数,同时值小于hash-max-ziplist-value配置字节时使用,结构更紧凑实现多个元素连续存储.

hashtable:无法满足ziplist条件时使用作为内部实现

3.3 使用场景

缓存用户信息,即呈现关系型数据库的行信息

但与关系型数据库的不同:

哈希类型是稀疏的,而关系型数据库是完全结构化的。

关系型数据库可以做复杂关系查询,redis来模拟维护成本太高了。

缓存用户信息三种方法:

1)原生字符串类型

2)序列化字符串类型

3)哈希类型

各自优缺点(待补充)

4 列表

存储字符串的双端队列,有序可重复

4.1 命令

向右插入元素rpush key value[value...]
从左插入元素lpush key value[value...]
某个元素前后插入linsert key before/after pivot value
获取指定范围内的元素列表

lrange key start end

获取列表指定索引下标的元素lindex key index
获取列表长度llen key
从列表左侧弹出元素lpop key
从列表右侧弹出元素rpop key
删除指定元素

lrem key count value

count >0 删除从左到右count个元素

count <0 删除从右到左|count|个元素

count =0 删除所有

按照索引范围修剪列表ltrim key start end
修改指定索引下标的元素lset key index newValue
阻塞式弹出

blpop key [key...] timeout

brpop key [key...] timeout

  

 

4.2 内部编码

ziplist:列表的元素个数小于list-max-ziplist-entries配置(默认512)个数,同时列表中每的元素值小于lisst-max-ziplist-value配置(默认64)字节时使用,减少内存的使用

linkedlist:无法满足ziplist条件时使用作为内部实现

redis3.2提供了一个quicklist的内部编码,用linkedlist存储ziplist的节点

4.3 使用场景

消息队列lpush+brpop

生产者客户端使用lpush从列表左侧插入元素,多个消费者客户端使用brpop阻塞式抢占列表尾部的元素,多个客户端保证了消费的负载均衡和高可用性

文章列表。

5 集合

5.1 命令

集合内操作: 
添加元素sadd key element[element...]
删除元素srem key element[element...]
计算元素个数scard key
判断元素是否在集合中 sismember key element
随机从集合返回指定个数元素srandmember key [count]
从集合随机弹出元素spop key
获取所有元素

smembers key

集合间操作: 
求多个集合的交集

sinter key [key...]

求多个集合的并集sunion key [key...]
求多个集合的差集sdiff key [key...]
将交集/并集/差集的结果保存

sinterstore destination key[key...]

sunionstore destination key[key...]

sdiffstore destination key[key...]

  

5.2 内部编码

intset:集合中的元素都是整数且元素个数小于set-max-inset-entries配置(默认512)个数,redis会选用它来减少内存的使用

hashtable:无法满足intset条件时使用作为内部实现

 

5.3 使用场景

标签:sadd

用户和标签的关系维护应该放一个事务中进行

生成随机数:spop/srandmember

社交需求(social graph):sadd+sinter

 

6 有序集合

有序集合给每个元素设置一个分值(score)来作为排序依据。不允许集合元素重复,但是score可以重复。可以做排行榜系统/社交等

6.1 命令

集合内操作: 
添加成员

zadd key score  member[score member...]

有nx/xx/ch/incr四个选项

计算成员个数zcard key
计算某个成员分数zcount key member
计算成员排名

 zrank key member(从低到高)

zrevrank key member(从高到低)

删除成员srandmember key [count]
增加成员分数zincrby key increment member
返回指定排名范围的成员

zrange key start end [withscores]

zrevrange key start end [withscores]

返回指定分数范围的成员

zrangebyscore key min max [withscores] [limit offset count]

zrevrangebyscore key min max [withscores] [limit offset count]

返回指定分数范围的成员个数

 

zcount key min max

删除指定排名内的升序元素

zremrangebyrank key start end

删除指定分数范围的成员zremrangebyscore key min max
集合间操作:

 

交集zinterstore destinattion numkeys [key...] [weights weight [weight...]] [aggregate sum|min|max]
并集zunionstore destinattion numkeys [key...] [weights weight [weight...]] [aggregate sum|min|max]
交集zinterstore destinattion numkeys [key...] [weights weight [weight...]] [aggregate sum|min|max]

 

6.2 内部编码

ziplist:有序集合的元素个数小于zset-max-ziplist-entries配置(默认128)个数,同时列表中每的元素值小于zset-max-ziplist-value配置(默认64)字节时使用,减少内存的使用

skiplisst:无法满足ziplist条件时使用作为内部实现

6.3 使用场景

排行榜系统:

         添加用户赞数:zadd zincrby

         取消用户赞数:zrem

         展示获赞最多的用户:zrevrangebyrank

         展示用户信息以及用户分数:zscore zrank

7 键管理

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值