Redis基础与入门实战

redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。

 

总结来说,使用Redis的好处如下:

  • 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
  • 支持丰富数据类型,支持string,hash,list,set,zset
  • 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
  • 丰富的特性,可用于缓存,消息,计数,按key设置过期时间,过期后将会自动删除
  • 单线程,预防多线程的竞态问题

一、Redis的使用


1.redis数据结构 – strings

set mystr "hello world!" //设置字符串类型
get mystr //读取字符串类型

我们还可以通过字符串类型进行数值操作:

127.0.0.1:6379> set mynum "2"
OK
127.0.0.1:6379> get mynum
"2"
127.0.0.1:6379> incr mynum
(integer) 3
127.0.0.1:6379> get mynum
"3"

在遇到数值操作时,redis会将字符串类型转换成数值。
由于INCR等指令本身就具有原子操作的特性,所以我们完全可以利用redis的INCR、INCRBY、DECR、DECRBY等指令来实现原子计数的效果,假如,在某种场景下有3个客户端同时读取了mynum的值(值为2),然后对其同时进行了加1的操作,那么,最后mynum的值一定是5。不少网站都利用redis的这个特性来实现业务上的统计计数需求

如果有多客户同时执行setnx,只有一个能设置成功,可做分布式

set命令也支持批量处理,mset/mget批量设置和批量获取。批量操作提高了执行效率,否则一批次的n次查询需要发起n次请求。

2.redis数据结构 – 哈希

Hash存的是字符串和字符串值之间的映射,特别适合存储对象,比如一个用户要存储其全名、姓氏、年龄等等,就很适合使用哈希(此处如果用String类型就会占用过多的key空间)。

  • hset key field value 单个赋值
  • hmset key field value [filed value]...批量赋值

//建立哈希,并赋值
127.0.0.1:6379> HMSET user:001 username antirez password P1pp0 age 34 
OK

//列出哈希的内容
127.0.0.1:6379> HGETALL user:001 
1) "username"
2) "antirez"
3) "password"
4) "P1pp0"
5) "age"
6) "34"

//更改哈希中的某一个值
127.0.0.1:6379> HSET user:001 password 12345 
(integer) 0

//再次列出哈希的内容
127.0.0.1:6379> HGETALL user:001 
1) "username"
2) "antirez"
3) "password"
4) "12345"
5) "age"
6) "34"

在一般应用场景中,用户信息缓存化,可以有三种解决方案,1、set存储,2、对象信息序列化存储,3、hset存储,用户信息不经常修改的情况可用2,value值不大的情况可以用3.

3.redis数据结构 – lists

首先要明确一点,redis中的lists在底层实现上并不是数组,而是链表,因此是增删改快,定位较慢。
lists的常用操作包括LPUSH、RPUSH、LRANGE等。我们可以用LPUSH在lists的左侧插入一个新元素,用RPUSH在lists的右侧插入一个新元素,用LRANGE命令从lists中指定一个范围来提取元素。

//新建一个list叫做mylist,并在列表头部插入元素"1"
127.0.0.1:6379> lpush mylist "1" 
//返回当前mylist中的元素个数
(integer) 1 
//在mylist右侧插入元素"2"
127.0.0.1:6379> rpush mylist "2" 
(integer) 2
//在mylist左侧插入元素"0"
127.0.0.1:6379> lpush mylist "0" 
(integer) 3
//列出mylist中从编号0到编号1的元素
127.0.0.1:6379> lrange mylist 0 1 
1) "0"
2) "1"
//列出mylist中从编号0到倒数第一个元素
127.0.0.1:6379> lrange mylist 0 -1 
1) "0"
2) "1"
3) "2"

4.redis数据结构 – set集合

Redis的集合,是一种无序的集合,集合中的元素没有先后顺序。集合相关的操作也很丰富,如添加新元素、删除已有元素、取交集、取并集、取差集等。

//向集合myset中加入一个新元素"one"
127.0.0.1:6379> sadd myset "one" 
(integer) 1
127.0.0.1:6379> sadd myset "two"
(integer) 1
//列出集合myset中的所有元素
127.0.0.1:6379> smembers myset 
1) "one"
2) "two"
//判断元素1是否在集合myset中,返回1表示存在
127.0.0.1:6379> sismember myset "one" 
(integer) 1
//判断元素3是否在集合myset中,返回0表示不存在
127.0.0.1:6379> sismember myset "three" 
(integer) 0
//新建一个新的集合yourset
127.0.0.1:6379> sadd yourset "1" 
(integer) 1
127.0.0.1:6379> sadd yourset "2"
(integer) 1
127.0.0.1:6379> smembers yourset
1) "1"
2) "2"
//对两个集合求并集
127.0.0.1:6379> sunion myset yourset 
1) "1"
2) "one"
3) "2"
4) "two"

使用场景:标签,社交,查询有共同兴趣爱好的人,智能推荐

5.redis数据结构-zset有序集合

同无序集合一样,存储string类型且不能重复。每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

redis 127.0.0.1:6379> ZADD key 1 redis
(integer) 1
redis 127.0.0.1:6379> ZADD key 2 mongodb
(integer) 1
redis 127.0.0.1:6379> ZADD key 3 mysql
(integer) 1
redis 127.0.0.1:6379> ZADD key 3 mysql
(integer) 0
redis 127.0.0.1:6379> ZADD key 4 mysql
(integer) 0
redis 127.0.0.1:6379> ZRANGE key 0 10 WITHSCORES
1) "redis"
2) "1"
3) "mongodb"
4) "2"
5) "mysql"
6) "4"

常用于排行榜,如视频网站需要对用户上传视频做排行榜,或点赞数

6.redis的全局命令

  • 查看所有键:keys *,也可以用*进行模糊匹配。
  • 键总数 dbsize 如果存在大量键,线上禁止使用此指令
  • 检查键是否存在:exists keyName 存在返回1,不存在返回0
  • 删除键:del keyName 返回删除键个数,删除不存在键返回0
  • 键过期:expire keyName seconds
  • 键的数据结构类型:type key 返回string,键不存在返回nil

Redis的命令很多,提供如下网站可以作为工具网站进行查阅:

二、Redis持久化机制

Redis是一个支持持久化的内存数据库,为了防止数据丢失Redis需要经常将内存中的数据同步到磁盘来保证持久化,它提供了两种持久化的方式,分别是RDB(Redis DataBase)AOF(Append Only File)

1.RDB(Redis DataBase)

简而言之,就是在不同的时间点,将redis存储的数据生成快照并存储到磁盘等介质上
Redis默认为该方式,内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb(如果需要恢复数据,只需将备份文件dump.rdb 移动到 redis 安装目录并启动服务即可)。可以通过配置设置自动做快照持久化的方式。配置redis在n秒内如果超过m个key被修改就自动做快照,下面是默认的快照保存配置。

save 900 1         #900秒内如果超过1个key被修改,则发起快照保存
save 300 10        #300秒内容如超过10个key被修改,则发起快照保存
save 60 10000      #60秒内容如超过10000个key被修改,则发起快照保存

 

client 也可以使用save或者bgsave命令手动通知redis做一次快照持久化。save操作是在主线程中保存快照的,由于redis是用一个主线程来处理所有 client的请求,这种方式会阻塞所有client请求,不推荐使用。

RDB利弊 原因
优点1 压缩后的二进制文,适用于备份、全量复制,用于灾难恢复
优点2 大数据量时,加载RDB恢复数据远快于AOF方式
缺点1 无法做到实时持久化,每次都要创建子进程,频繁操作成本过高
缺点2 保存后的二进制文件,存在老版本不兼容新版本rdb文件的问题

2.AOF(Append Only File)

AOF则是换了一个角度来实现持久化,那就是将redis执行过的所有写指令记录下来,在下次redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了,相关配置如下:


 

appendonly  no         # redis默认关闭AOF机制,可以将no改成yes实现AOF持久化
appendfsync always     # 每次有数据修改发生时都会写入AOF文件。
appendfsync everysec   # 每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync no         # 从不同步。高效但是数据不会被持久化。

具体操作方式:如何从AOF恢复数据?1. 设置appendonly yes;2. 将appendonly.aof放到dir参数指定的目录;3. 启动Redis,Redis会自动加载appendonly.aof文件。

其实RDB和AOF两种方式也可以同时使用,在这种情况下,如果redis重启的话,则会优先采用AOF方式来进行数据恢复,这是因为AOF方式的数据恢复完整度更高。如果你没有数据持久化的需求,也完全可以关闭RDB和AOF方式,这样的话,redis将变成一个纯内存数据库,就像memcache一样。

重启时恢复加载AOF与RDB顺序及流程:

  • 当AOF和RDB文件同时存在时,优先加载AOF
  • 若关闭了AOF,加载RDB文件
  • 加载AOF/RDB成功,redis重启成功
  • AOF/RDB存在错误,redis启动失败并打印错误信息

3. Redis主从下的持久化方案设计

  • Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
  • 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
  • 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内
  • 尽量避免在压力很大的主库上增加从库
  • 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...。这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。



作者:YitaiCloud
链接:https://www.jianshu.com/p/7ef03afd01c6
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 


 

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

微信扫一扫

微信扫一扫

微信扫一扫,分享到朋友圈

Redis基础与入门实战