Redis原理及应用

 

1.什么是redis

redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、key-value数据库,并提供多种语言API,

支持的String(也可以是数字)、list(链表)、hash、set、zset数据结构。

2.redis的应用场景

2.1热数据缓存(减少数据库的压力)

热点数据(经常被查询,但不是经常修改或删除的数据)具体的处理过程如下

1.查询:select 数据库前先查询redis是否有数据,如果有,直接返回,不查询数据库;如果没有,查询数据库,并把数据插入的redis。

2.删除:先清空redis中的数据,之后删除数据库中的数据。

3.修改:先删除redis中的数据,之后修改数据库。

上面修改的逻辑,如果并发量很高的情况下会有如下的问题:

a.当删除redis中的数据后,另一个线程执行了查询操作,重新将数据插入redis,

b.此时再修改数据库中的数据。导致redis中的为修改前的数据。这个脏数据会一直存在于redis中,知道下一次的update或delete

2.2计数器

例如统计登录用户数,点击量等场景,由于redis是单线程的,所以可以避免并发问题,保证数据的正确。相关命令为:INCRBY、INCR

2.3队列

利用redis的list数据类型,可以实现分布式队列功能,与常用的ActiveMQ、RocketMQ类似,可以简单实用如果对数据的一致性要求较高建议使用专业的消息中间件

2.4分布式锁

利用redis的setnx命令实现,此命令只有在key不存在的时候才会插入数据成功。当多个线程同时去调用此命令的时候,同时只有一个成功,调用成功的线程获取到锁。处理完成后delete释放锁。

2.5排行榜

利用redis的zset数据类型,使用zadd 将数据插入到redis中

2.6最新的项目列表

下面这个语句常用来显示最新项目,随着数据多了,查询毫无疑问会越来越慢。

SELECT * FROM foo WHERE ... ORDER BY time DESC LIMIT 10 

当数据不断增多时,会影响数据库的性能,我们可以利用redis的list数据类型,在每次添加数据时,使用lpush将数据插入到redis中,并设置list的长度为10,每次取最新的数据时,只需要从redis获取,提高了程序的性能。

2.7秒杀系统

基于list数据类型。秒杀开始前,查询商品的库存,在list中插入对应库存的数据(此数据是没有实际意义的,仅仅代表一件商品),秒杀开始的逻辑。以下为代码

/* 模拟抢购操作,抢购前判断redis队列库存量 */
 $count=\Redis::lpop('goods_store:1');//lpop是移除并返回列表的第一个元素。
 if(!$count)
    return '已经抢光了哦';
 /* 下面处理抢购成功流程 */
\DB::table('goods')->decrement('num', 1);//减少num库存字段

3.redis常用命令

3.1字符类型

set key value 设置值
get key  获取值
incr key 原子自增
decr key 原子递减
incrby key increment 递增指定数值
decrby key increment 递减指定数值
append key value 追加指定字符
strlen key 获取value的长度(value可以是数值类型)
mget key key... 获取多个可以的值
mset key value key value 设置多个可以的值
setnx key value 指定值,只有在key不存的时候才能设置成功,可以用来做分布式锁
del key key 删除多个key

3.2 列表类型

list 可以存储一个有序的列表
LPUSH/RPUSH key value value … 向指定key中左/右添加多个value
llen key 获得列表的长度
lrange key start end 获取指定范围的数据,索引可以是负数-1 代表最后一个元素
lrem key count value 从左侧开始便利,删除count个value值
lset key index value 修改指定索引的value值
lpop/rpop key 左/右弹出指定key的value值

3.3hash类型

hash不支持数据类型的嵌套,适合存储对象

hset key field value 设置值
hget key field 获取值
hmset key filed value [filed value …]  一次性设置多个值
hmget key field field …  一次性获得多个值
hgetall key  获得hash的所有信息,包括field和value
hexists key field 判断字段是否存在。 存在返回1. 不存在返回0
hdel key field [field …] 删除一个或者多个字段
hincryby key field increment 递增指定数值
hsetnx key field value 设置值,只有在field不存在是才能设置成功。类似setnx

3.4set集合类型

set不能存重复的数据,而且是无序的
sadd key member [member ...] 增加数据; 如果value已经存在,则会忽略存在的值,并且返回成功加入的元素的数量
srem key member  删除元素
smembers key 获得所有数据

sdiff key key …  对多个集合执行差集运算
sunion key key ...对多个集合执行并集操作, 同时存在在两个集合里的所有值

3.5zset有序集合

zadd key score member ...添加多个元素

zrange key start stop [withscores] 去获得元素。 withscores是可以获得元素的分数
如果两个元素的score是相同的话,那么根据(0<9<A<Z<a<z) 方式从小到大
zrem key member member... 删除多个元素

4.redis事务

事务相关的命令

multi 开启一个事务
discard 清空事务队列中的命令,并退出事务
exec 执行事务
watch key [key...]监控一个或多个key
unwatch 取消所有key的监控

事务的注意事项

1.redis会将事务中的所有命令序列化,然后按照顺序执行,redis在执行一个客户端的事务时,不会执行另一个客户端的请求。

2.redis中能保证事务的所有命令都被执行,即使其中一条命令执行错误,也不会影响后续命令的执行(不会执行回滚操作),这里的错误指程序员对value执行不支持的操作,如对String类型执行incr 操作。

3.如果在添加命令的过程中,redis检测到语法错误,不会执行事务中的命令。

//正常事务的样例
set name zhangsan
set age 1
multi //开启事务
set name lisi //添加命令
incr age //添加命令
exec //执行事务

//退出事务
multi
set name lisi
set age 1
discard //退出事务

//异常事务 事务中所有的命令都不会执行
set name zhangsan
set age 1
multi
set name lisi
incr age 2 //错误的语法
exec //提交事务

//异常事务 部分执行
set name zhangsan 
set age 1
multi
set name lisi
set age a
incr age //错误的命令 age此时为String类型
exec //提交事务 incr age执行失败 其它的成功

//watch 样例
set name zhangsan
set age 1
watch name //监听name的值
multi
set name lisi
set age a 
exec 
//在watch后exec执行前,如果其他客户端有修改name的值,此事务会执行失败;否则会执行成功,执行成功后watch的key会自动释放。

5.持久化模式

redis支持RDB和AOF两种持久化方式,

RDB:快照模式,redis会定时将内存中的数据写入到磁盘文件中,在redis重启的时候会将文件中的数据加载到redis 

AOF:日志模式,redis会将所有的事务操作写入到.aof文件中,在重启时,redis会读取并执行aof文件中的命令,来恢复数据

可以选择使用其中一种,也可以混合使用;

RDB、AOF两者的对比:

RDB:

优点:1.RDB在持久化时,会fork以个子进程,由子进程完成持久化工作,可以避免服务进程执行IO操作

2.相比于AOF机制,如果数据量较大的情况下RDB恢复数据较快;RDB只需要加载数据,而AOF需要重新执行一遍命令。

缺点:在redis持久化之前,如果redis宕机了,还没来得及持久化的数据会丢失,对于可靠性要求较高的系统不适合使用本模式

AOF:1.基于日志的模式,可以使redis具有较高的可靠性,redis提供了三种AOF日志写入策略,既每秒同步、每修改同步、不同步。每秒同步会将1s内所有命令一同执行,如果出现宕机,那么这1秒内的数据将不会同步;每修改同步,既每次命令都同步写到文件中;不同步既redis不会执行同步。

2.aof写入文件的策略为append模式,因此即使同步的过程中redis出现宕机,也不会影响文件内容的格式,如果出现一个命令没有写入完全的情况,redis在重启的时候会通过内置的redis-check-aof对aof文件的格式进行检查,并修复文件。

3.如果aof文件过大,redis还可以开启aof的rewrite模式,对重复的命令进行过滤,以减小文件的大小,在重启的时候也可以加快redis的启动速度。

持久化的常用配置

RDB
//rdb dump频率设置
save 900 1              #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
save 300 10            #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
save 60 10000        #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。

AOF三种同步方式
appendfsync always     #每次有数据修改发生时都会写入AOF文件。
appendfsync everysec  #每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync no          #从不同步。高效但是数据不会被持久化。

集群模式

redis支持三种集群方式分别为,主从模式、哨兵模式、集群模式

主从模式:redis集群支持1主n从,主从节点存储的都是全量的数据,主节点会将数据同步到从节点,从节点可以处理读请求,主节点处理读写请求,可以实现读写分离,减少主节点的压力;缺点是当主节点宕机后,不会实现集群的自动选举;

哨兵模式:通常为1主2从3哨兵部署方式;集群中master-slave节点都存储的全量数据;主节点负责处理读写请求,将数据同步到从节点;从节点处理读取请求,并接受主节点的数据;哨兵节点负责监控主节点的状态,当主节点挂掉后,哨兵节点会在slaver节点中选出一个为master节点;

集群模式:在主从及哨兵模式中由于每个节点都是存储的全量数据,导致集群的容量受单个节点容量的限制;

Redis Cluster中,Sharding采用slot(槽)的概念,一共分成16384个槽,这有点儿类似前面讲的pre sharding思路。对于每个进入Redis的键值对,根据key进行散列,分配到这16384个slot中的某一个中。使用的hash算法也比较简单,就是CRC16后16384取模。Redis集群中的每个node(节点)负责分摊这16384个slot中的一部分,也就是说,每个slot都对应一个node负责处理。当动态添加或减少node节点时,需要将16384个槽做个再分配,槽中的键值也要迁移。当然,这一过程,在目前实现中,还处于半自动状态,需要人工介入。Redis集群,要保证16384个槽对应的node都正常工作,如果某个node发生故障,那它负责的slots也就失效,整个集群将不能工作。为了增加集群的可访问性,官方推荐的方案是将node配置成主从结构,即一个master主节点,挂n个slave从节点。这时,如果主节点失效,Redis Cluster会根据选举算法从slave节点中选择一个上升为主节点,整个集群继续对外提供服务。这非常类似服务器节点通过Sentinel监控架构成主从结构,只是Redis Cluster本身提供了故障转移容错的能力。

 

slot(槽)的概念,在redis集群中一共会有16384个槽,

根据key 的CRC16算法,得到的结果再对16384进行取模。 假如有3个节点

node1  0 5460

node2  5461 10922

node3  10923 16383

节点新增

node4  0-1364,5461-6826,10923-12287

删除节点

先将节点的数据移动到其他节点上,然后才能执行删除

市面上提供了集群方案

  1. redis shardding   而且jedis客户端就支持shardding操作  SharddingJedis ; 增加和减少节点的问题; pre shardding

3台虚拟机 redis 。但是我部署了9个节点 。每一台部署3个redis增加cpu的利用率

9台虚拟机单独拆分到9台服务器

  1. codis基于redis2.8.13分支开发了一个codis-server
  2. twemproxy  twitter提供的开源解决方案
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值