Redis
Redis 是一种内存数据库,它主要是用来提高网站性能
的。
快速入门
安装
Docker 安装+启动
- 下载 Redis 镜像
docker pull redis
- 创建并启动容器
docker run -d --name redis -p 6379:6379 redis
mac 安装
1.安装命令
brew install redis
2.修改配置文件
vim /usr/local/etc/redis.conf
3.默认情况下绑定了本机127的ip,不允许远程访问
#bind 127.0.0.1
protected-mode yes
改为
protected-mode no
4.测试是否安装成功
redis-cli ping
5.启动/关闭/重启 服务
brew services start/stop/restart redis
或
redis-server /usr/local/etc/redis.conf
6.bash交互界面
redis-cli
windows 安装
下载软件包,解压缩,软件包中最重要的三个文件:
- redis-server:服务器程序
- redis-cli:客户端程序
- redis.windows.conf:配置文件
windows启动
命令行方法
在 windows 中直接打开命令行并运行 redis-server 即可启动服务器。
方法一:
redis-server.exe redis.windows.conf // 先切换到redis根目录,windows下启动,带配置文件
方法二:
1) 添加根目录为环境变量
2) 启动
redis-server.exe D:\redis\redis.windows.conf //配置文件目录用绝对路径
启动之后默认监听 6379
端口。
连接
服务器启动之后,就可以使用 redis-cli
来连接服务器进行操作。
打开命令行并执行 redis-cli
退出
在命令行中执行 exit
退出连接。
数据类型
Redis 中提供了多种数据类型来保存数据:
- 字符串(string)
- 列表(list)
- 集合(set)
- 有序集合(sorted set)
- 哈希(hash)
每种数据类型都提供了很多指令来进行操作:
字符串
get 和 set
字符串是最基本的数据类型。
使用 set
指令来保存字符串数据:
set 键 值
值最大为 512M
。
使用 get
指令读取字符串数据:
get 键
自增和自减
还可以对数字类型使用 incr
和 decr
实现 加1 和 减1 操作。
set money 100
incr money // 101
incr money // 102
decr money // 101
也可以使用 incrby 数字
和 decrby 数字
实现 加N 和 减N 操作。
set money 100
incrby money 50 // 150
decrby money 20 // 130
mget 和 mset
我们也可以使用 mget
和 mset
批量添加和读取数据。
mset a 10 b 10 c 10
mget a b c // 10 20 30
exists 、 del 和 type
exists :判断一个键是否存在。
del:删除一个键值对
type:查看数据类型
set name 'tom'
type name // string
exists name // 1
del name // 1
exists name // 0
过期
我们可以为 Redis 中保存的数据设置一个过期时间 ,过期时间到了之后会自动从 Redis 中删除该数据。
使用 expire
设置过期时间:
expre 键 过期时间(秒) //需要实现set设置过值
可以使用 ttl
指令查看剩余的过期时间。
ttl 键 // -1: 已过期 -2: 未设置
也可以在 set 时设置过期时间:
set 键 值 ex 过期时间
应用场景
主要用来做网站数据的缓存,比如:使用 Redis 保存 “销量最高的10件商品”、“最活跃的用户”等等。
列表
列表( List )是一种按顺序保存一组数据的结构,有点类型于数组。
lpush 和 rpush
lpush:从列表左侧
添加一个数据。
rpush:从列表右侧
添加一个数据。
lpush 键 值
比如:
lpush class php // php
lpush class js // js php
lpush class css // css js php
rpush class html // css js php html
// 也可以一次添加多个值
lpush class a b c // c b a css js php html
lrange
lrange:从左侧取出多个值,读取之后值还在列表中。
lrange 键 开始下标 结束下标
下标说明:
- 从 0 开始
- 可以使用负数,-1:最后一个 , -2:倒数第2个
lpop 、 rpop 和 rpoplpush
lpop:最出最左侧的一个值,然后从列表中删除该值。
rpop:从右侧取出一个值,然后从列表中删除该值。
rpoplpush:从列表右侧取出一个值,然后放到另一个列表的左侧。
lpush class a b c // c b a
rpoplpush class class // a c b
rpop class // 得到 a ,列表变成 c b
lpop class // 得到 c , 列表变成 b
ltrim
ltrim:语法和 lrange 类似,功能是截取出列表中一个范围的数据,范围外的数据被删除。
lpush class a b c d // d c b a
ltrim class 1 2 // 队列中只剩 c b
brpop
b:阻塞。
brpop:从列表右侧取出一个数据,如果列表中没有数据就阻塞等待,直到有另一个客户端向列表中添加了数据才返回。
brpop 键 等待时间(秒)
等待时间如果设置为 0 则代表永远等待直到有数据为止。
应用场景:消息队列。
应用场景:
- 秒杀、抢票
- 保存最新前N的xxx数据(
最新排行榜
) - 消息队列
哈希
哈希(Hash)用来保存多组键值对的数据,有些类似于 PHP 中的关联数组。
hmset
hmset:可以保存 hash 数据。
hmset 键 字段1 值1 字段2 值2 ...
示例、保存 ID=100 的用户信息
hmset user:100 name tom gender 男 birth 2019-10-10
hget 和 hgetall
hget:获取某一个字段值
hgetall:获取所有字段值
集合
集合(set)是一组 无序
、不重复
的字符串。
sadd、smembers 和 sismember
sadd:向集合中添加数据
smembers:获取集合中所有数据
sismember:判断一个数据是否在集合中
sadd nums 1 2 3
smembers nums // 1 2 3
sismember nums 3 // 1
sismember nums 4 // 0
spop、srem、smove
spop:从集合中随机取出一个数据,并从集合中删除该数据。
srem:从集合中移动一个或者多个元素
smove:将一元素从一个集合移动到另一个集合
sunion、sinter、sdiff
sunion:返回多个集合的并集
sinter:返回多个集合的交集
sdiff:前一个集中有,后一个集合中没有的数据
交集:同时在多个集合中
并集:合并集合
总结
- 集合中的数据不重复
- 无序
应用场景
a. 好友系统 b. 发牌游戏 c. 抽奖等
有序集合
有序集合(sorted sets):是一组有 顺序
、不重复
的一数据。
集合中的每个数都可以设置一个分值,然后就可以根据分值进行排序。
zadd
可以使用 zadd
向集合中添加数据。
zadd 键名 分值 数据
zrange
zrange:取出排在某个区间内的成员。
zrange 键名 开始下标 结束下标 withscores
示例、显示整个有序集成员
redis > ZRANGE salary 0 -1 WITHSCORES
1) "jack"
2) "3500"
3) "tom"
4) "5000"
5) "boss"
6) "10086"
示例、显示排在2、3位的成员
redis > ZRANGE salary 1 2 WITHSCORES
1) "tom"
2) "5000"
3) "boss"
4) "10086"
zrank
zrank:获取某个成员的排名
zrank 键名 值
总结
- 值不重复
- 有顺序
应用场景
排行榜、浏览量、商品销量等等
频道
订阅
我们可以使用 subscribe
订阅一个或者多个频道,当有客户端向频道发消息时就可以收到。
subscribe 频道1 频道2 ...
发布
可以使用 publish
向一个频道中发送消息。
publish 频道 消息
场景
消息队列
事务
事务可以使多个指令都执行成功
,或者都执行失败
,保存完整性。
multi 、 exec和discard
multi:开启一个事务,后续执行的指令将都保存到事务队列中(开启事务)
exec:执行事务队列中所有的指令(提交事务)
discard:取消事务,清除事务列表中所有指令(取消事务)
watch 和 unwatch
watch:监听一个或者多个key,如果在执行一个事务时,监听的 key 被修改,那么中止执行会失败
unwatch:取消所有监听
predis 扩展
要使用 PHP 操作 Redis 需要安装扩展才可以,有两种扩展可以使用:
- 使用 C 语言编写的 redis 扩展
- 使用 PHP 语言编写的 predis 类库
安装 C 语言的 redis 扩展
- 到 pecl.php.net 中下载相应版本的扩展包
- 把下载的 php_redis.dll 复制到扩展目录中。
可以在 phpinfo() 中查看扩展目录
- 修改 php.ini 添加一行
extension=php_redis.dll
- 重启 APACHE 服务器
- 安装成功之后可以在 phpinfo() 中查看:
下载
PHP 写的扩展叫 predis
,可以从 PHP 的包仓库中下载:
使用 composer 下载安装:
composer require predis/predis
使用 predis
要使用 composer 下载的类库,我们需要先引入自动加载文件:
require(ROOT.'vendor/autoload.php');
然后就可以在项目中使用了。
1、连接 Redis 服务器
$client = new \Predis\Client([
'scheme' => 'tcp',
'host' => '10.0.0.1',
'port' => 6379,
]);
- 数据操作
//普通set/get操作
$redis->set('library', 'predis');
$retval = $redis->get('library');
echo $retval; //显示 'predis'
//setex set一个存储时效
$redis->setex('str', 10, 'bar'); //表示存储有效期为10秒
//setnx/msetnx相当于add操作,不会覆盖已有值
$redis->setnx('foo',12); //true
$redis->setnx('foo',34); //false
//getset操作,set的变种,结果返回替换前的值
$redis->getset('foo',56);//返回34
// incrby/incr/decrby/decr 对值的递增和递减
$redis->incr('foo'); //foo为57
$redis->incrby('foo',2); //foo为59
//exists检测是否存在某值
$redis->exists('foo');//true
//del 删除
$redis->del('foo');//true
//type 类型检测,字符串返回string,列表返回 list,set表返回set/zset,hash表返回hash
$redis->type('foo');//不存在,返回none
$redis->set('str','test');
$redis->type('str'); //字符串,返回string
//append 连接到已存在字符串
$redis->append('str','_123'); //返回累加后的字符串长度8,此进str为 'test_123'
//setrange 部分替换操作
$redis->setrange('str',0,'abc'); //返回3,参数2为0时等同于set操作
$redis->setrange('str',2,'cd');//返回4,表示从第2个字符后替换,这时'str'为'abcd'
//substr 部分获取操作
$redis->substr('str',0,2);//表示从第0个起,取到第2个字符,共3个,返回'abc'
//strlen 获取字符串长度
$redis->strlen('str'); //返回4
//setbit/getbit 位存储和获取
$redis->setbit('binary',31,1); //表示在第31位存入1,这边可能会有大小端问题?不过没关系,getbit 应该不会有问题
$redis->getbit('binary',31); //返回1
//keys 模糊查找功能,支持*号以及?号(匹配一个字符)
$redis->set('foo1',123);
$redis->set('foo2',456);
$redis->keys('foo*'); //返回foo1和foo2的array
$redis->keys('f?o?'); //同上
//randomkey 随机返回一个key
$redis->randomkey(); //可能是返回 'foo1'或者是'foo2'及其它任何一存在redis的key
//rename/renamenx 对key进行改名,所不同的是renamenx不允许改成已存在的key
$redis->rename('str','str2'); //把原先命名为'str'的key改成了'str2'
//expire 设置key-value的时效性,ttl 获取剩余有效期,persist 重新设置为永久存储
$redis->expire('foo', 1); //设置有效期为1秒
$redis->ttl('foo'); //返回有效期值1s
$redis->expire('foo'); //取消expire行为
//dbsize 返回redis当前数据库的记录总数
$redis->dbsize();
/*
队列操作
*/
//rpush/rpushx 有序列表操作,从队列后插入元素
//lpush/lpushx 和rpush/rpushx的区别是插入到队列的头部,同上,'x'含义是只对已存在的key进行操作
$redis->rpush('fooList', 'bar1'); //返回一个列表的长度1
$redis->lpush('fooList', 'bar0'); //返回一个列表的长度2
$redis->rpushx('fooList', 'bar2'); //返回3,rpushx只对已存在的队列做添加,否则返回0
//llen返回当前列表长度
$redis->llen('fooList');//3
//lrange 返回队列中一个区间的元素
$redis->lrange('fooList',0,1); //返回数组包含第0个至第1个共2个元素
$redis->lrange('fooList',0,-1);//返回第0个至倒数第一个,相当于返回所有元素,注意redis中很多时候会用到负数,下同
//lindex 返回指定顺序位置的list元素
$redis->lindex('fooList',1); //返回'bar1'
//lset 修改队列中指定位置的value
$redis->lset('fooList',1,'123');//修改位置1的元素,返回true
//lrem 删除队列中左起指定数量的字符
$redis->lrem('fooList',1,'_'); //删除队列中左起(右起使用-1)1个字符'_'(若有)
//lpop/rpop 类似栈结构地弹出(并删除)最左或最右的一个元素
$redis->lpop('fooList'); //'bar0'
$redis->rpop('fooList'); //'bar2'
//ltrim 队列修改,保留左边起若干元素,其余删除
$redis->ltrim('fooList', 0,1); //保留左边起第0个至第1个元素
//rpoplpush 从一个队列中pop出元素并push到另一个队列
$redis->rpush('list1','ab0');
$redis->rpush('list1','ab1');
$redis->rpush('list2','ab2');
$redis->rpush('list2','ab3');
$redis->rpoplpush('list1','list2');//结果list1 =>array('ab0'),list2 =>array('ab1','ab2','ab3')
$redis->rpoplpush('list2','list2');//也适用于同一个队列,把最后一个元素移到头部list2 =>array('ab3','ab1','ab2')
//linsert 在队列的中间指定元素前或后插入元素
$redis->linsert('list2', 'before','ab1','123'); //表示在元素'ab1'之前插入'123'
$redis->linsert('list2', 'after','ab1','456'); //表示在元素'ab1'之后插入'456'
//blpop/brpop 阻塞并等待一个列队不为空时,再pop出最左或最右的一个元素(这个功能在php以外可以说非常好用)
//brpoplpush 同样是阻塞并等待操作,结果同rpoplpush一样
$redis->blpop('list3',10); //如果list3为空则一直等待,直到不为空时将第一元素弹出,10秒后超时
/**
set表操作
*/
//sadd 增加元素,返回true,重复返回false
$redis->sadd('set1','ab');
$redis->sadd('set1','cd');
$redis->sadd('set1','ef');
//srem 移除指定元素
$redis->srem('set1','cd'); //删除'cd'元素
//spop 弹出首元素
$redis->spop('set1');
//smove 移动当前set表的指定元素到另一个set表
$redis->sadd('set2','123');
$redis->smove('set1','set2','ab');//移动'set1'中的'ab'到'set2',返回true or false
//scard 返回当前set表元素个数
$redis->scard('set2');//2
//sismember 判断元素是否属于当前表
$redis->sismember('set2','123'); //true or false
//smembers 返回当前表的所有元素
$redis->smembers('set2'); //array('123','ab');
//sinter/sunion/sdiff 返回两个表中元素的交集/并集/补集
$redis->sadd('set1','ab');
$redis->sinter('set2','set1'); //返回array('ab')
//sinterstore/sunionstore/sdiffstore 将两个表交集/并集/补集元素copy到第三个表中
$redis->set('foo',0);
$redis->sinterstore('foo','set1'); //这边等同于将'set1'的内容copy到'foo'中,并将'foo'转为set表
$redis->sinterstore('foo',array('set1','set2')); //将'set1'和'set2'中相同的元素copy到'foo'表中,覆盖'foo'原有内容
//srandmember 返回表中一个随机元素
$redis->srandmember('set1');
/**
有序set表操作
*/
//sadd 增加元素,并设置序号,返回true,重复返回false
$redis->zadd('zset1',1,'ab');
$redis->zadd('zset1',2,'cd');
$redis->zadd('zset1',3,'ef');
//zincrby 对指定元素索引值的增减,改变元素排列次序
$redis->zincrby('zset1',10,'ab');//返回11
//zrem 移除指定元素
$redis->zrem('zset1','ef'); //true or false
//zrange 按位置次序返回表中指定区间的元素
$redis->zrange('zset1',0,1); //返回位置0和1之间(两个)的元素
$redis->zrange('zset1',0,-1);//返回位置0和倒数第一个元素之间的元素(相当于所有元素)
//zrevrange 同上,返回表中指定区间的元素,按次序倒排
$redis->zrevrange('zset1',0,-1); //元素顺序和zrange相反
//zrangebyscore/zrevrangebyscore 按顺序/降序返回表中指定索引区间的元素
$redis->zadd('zset1',3,'ef');
$redis->zadd('zset1',5,'gh');
$redis->zrangebyscore('zset1',2,9); //返回索引值2-9之间的元素 array('ef','gh')
//参数形式
$redis->zrangebyscore('zset1',2,9,'withscores'); //返回索引值2-9之间的元素并包含索引值 array(array('ef',3),array('gh',5))
$redis->zrangebyscore('zset1',2,9,array('withscores' =>true,'limit'=>array(1, 2))); //返回索引值2-9之间的元素,'withscores' =>true表示包含索引值; 'limit'=>array(1, 2),表示最多返回2条,结果为array(array('ef',3),array('gh',5))
//zunionstore/zinterstore 将多个表的并集/交集存入另一个表中
$redis->zunionstore('zset3',array('zset1','zset2','zset0')); //将'zset1','zset2','zset0'的并集存入'zset3'
//其它参数
$redis->zunionstore('zset3',array('zset1','zset2'),array('weights' => array(5,0)));//weights参数表示权重,其中表示并集后值大于5的元素排在前,大于0的排在后
$redis->zunionstore('zset3',array('zset1','zset2'),array('aggregate' => 'max'));//'aggregate' => 'max'或'min'表示并集后相同的元素是取大值或是取小值
//zcount 统计一个索引区间的元素个数
$redis->zcount('zset1',3,5);//2
$redis->zcount('zset1','(3',5)); //'(3'表示索引值在3-5之间但不含3,同理也可以使用'(5'表示上限为5但不含5
//zcard 统计元素个数
$redis->zcard('zset1');//4
//zscore 查询元素的索引
$redis->zscore('zset1','ef');//3
//zremrangebyscore 删除一个索引区间的元素
$redis->zremrangebyscore('zset1',0,2); //删除索引在0-2之间的元素('ab','cd'),返回删除元素个数2
//zrank/zrevrank 返回元素所在表顺序/降序的位置(不是索引)
$redis->zrank('zset1','ef');//返回0,因为它是第一个元素;zrevrank则返回1(最后一个)
//zremrangebyrank 删除表中指定位置区间的元素
$redis->zremrangebyrank('zset1',0,10); //删除位置为0-10的元素,返回删除的元素个数2
/**
hash表操作
*/
//hset/hget 存取hash表的数据
$redis->hset('hash1','key1','v1'); //将key为'key1' value为'v1'的元素存入hash1表
$redis->hset('hash1','key2','v2');
$redis->hget('hash1','key1'); //取出表'hash1'中的key 'key1'的值,返回'v1'
//hexists 返回hash表中的指定key是否存在
$redis->hexists ('hash1','key1'); //true or false
//hdel 删除hash表中指定key的元素
$redis->hdel('hash1','key2'); //true or false
//hlen 返回hash表元素个数
$redis->hlen('hash1'); //1
//hsetnx 增加一个元素,但不能重复
$redis->hsetnx('hash1','key1','v2'); //false
$redis->hsetnx('hash1','key2','v2'); //true
//hmset/hmget 存取多个元素到hash表
$redis->hmset('hash1',array('key3'=>'v3','key4'=>'v4'));
$redis->hmget('hash1',array('key3','key4')); //返回相应的值 array('v3','v4')
//hincrby 对指定key进行累加
$redis->hincrby('hash1','key5',3); //返回3
$redis->hincrby('hash1','key5',10); //返回13
//hkeys 返回hash表中的所有key
$redis->hkeys('hash1'); //返回array('key1','key2','key3','key4','key5')
//hvals 返回hash表中的所有value
$redis->hvals('hash1'); //返回array('v1','v2','v3','v4',13)
//hgetall 返回整个hash表元素
$redis->hgetall('hash1'); //返回array('key1'=>'v1','key2'=>'v2','key3'=>'v3','key4'=>'v4','key5'=>13)
应用
保存 SESSION
SESSION 中的数据默认是保存在文件中的,如果网站的访问量比较大,就会导致服务器要同时打开大量的 SESSION 文件 ,这会导致硬盘 IO 过于繁忙,最终导致硬盘阻塞,拖慢整个服务器的性能。
所以最好的方式是把 SESSION 保存到内存中。我们可以使用 ini_set
函数设置 SESSION 保存的位置:
// 动态的修改 php.ini 配置文件
ini_set('session.save_handler', 'redis'); // 使用 redis 保存 SESSION
ini_set('session.save_path', 'tcp://127.0.0.1:6379?database=3'); // 设置 redis 服务器的地址、端口、使用的数据库
session_start();
$_SESSION['name'] = 'tom';
把 SESSION 保存到 Redis 的好处:
- 性能快
- PHP 程序当运行在集群环境时 SESSION 会丢失,解决办法:把 SESSION 保存到 Redis 中实现 SESSION 共享。
数据缓存
网站中很多数据频繁被使用,如果每次都查询数据库会非常 的慢,所以我们一般是先从数据库中把要使用的数据取出来然后保存到 Redis 中,然后设置一个个过期,比如30分钟,然后我们程序就从 Redis 中取出数据,如果数据过期,再重新 读取数据库,再保存到 Redis 中。
哪些可以缓存:网站中的数据只要不是实时都要变化的就都可以缓存,比如:销量排行(每天统计一次,统计完之后保存到 Redis 中)、精品推荐、最周最活跃的用户、最新的10篇等等 这些首屏的数据。
消息队列
消息队列可以对系统 异步解耦
,以提高网站性能。
消费者程序
php.ini 中有一个配置项 default_socket_timeout
,这一项的意思:连接一个服务器的超时时间
,默认是60秒,如果我们希望在队列中没有数据时一直保存连接等待那么就需要设置这一项值为-1。
使用 brpop
指令阻塞读取队列。
// 设置 socket 永不超时
ini_set('default_socket_timeout', -1);
// 循环监听一个列表
while(true)
{
// 从队列中取数据,设置为永久不超时
$data = $redis->brpop(队列名称, 0);
// 处理数据
....... (比如发邮件)
}
生产者程序
使用 lpush
向队列中加入数据。
$redis->lpush(队列名称, 数据);
简单实例
- 消费者程序
这个程序负责在后台一直运行,它负责发邮件,所以项目中当有功能需要发邮件时,直接把邮件内容放到 user_emails
列表中即可,然后这个后台程序会负责发邮件。
<?php
// 连接永不断开
ini_set('default_socket_timeout', -1);
// 消费者程序
// 模块发邮件
function sendMail($content)
{
sleep(2);
file_put_contents('./mails/'.time(), $content);
}
// 监听消息队列,从队列中取出消息然后发邮件
require('./vendor/autoload.php');
// 连接 Redis
$client = new \Predis\Client([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
]);
echo "发邮件程序已经启动...\n";
while(true)
{
// 从队列的右侧取出消息,如果队列中没有消息就阻塞
$message = $client->brpop('user_emails', 0);
echo "收到消息,准备发邮件...\n";
// 取出消息之后就发邮件
sendMail($message[1]);
echo "邮件发送成功,开始监听下一个!\n";
}
- 生产者程序
当有程序需要发邮件时,只需要把消息放到队列中然后消费者程序会在后台发给我们发邮件。
<?php
// 负责注册
$user = 'tom';
$password = '12123';
$sql = 'insert into USER ...';
echo '数据库成功!';
echo '注册成功!';
// 监听消息队列,从队列中取出消息然后发邮件
require('./vendor/autoload.php');
// 连接 Redis
$client = new \Predis\Client([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
]);
// 出消息队列中放消息
$client->lpush('user_emails', '注册成功!欢迎加入!');
echo '完成 !!!';
总结:
- 消息队列用来解决系统的异步解耦
- 消息队列软件 :Redis、kafka、Rabbmq等等
- 消费者程序是在后台不间断的执行的
- 消费者程序在后台需要使用多进程不间断的执行(在PHP 里要使用 Swoole 或者 wokerman 来实现多进程)
- 在分布式系统和集群时使用
在连接 Redis 时可以使用 select
来切换数据库。
数据库主要用来在内存中把数据隔离开。
配置
复制
主从服务器。
!
搭建主从服务器只需要修改配置文件:然后开启这个服务器就是从服务器:
masterip:主服务器 IP 地址
masterport:主服务器端口号
安全
Redis 一般都是运行服务器内网中,不会暴露在外网,所以一般不需要设置密码,都是内部程序自己使用,如果要设置密码可以使用下面这一项:
一旦设置了密码,客户端在连接 Redis 之后,必须先使用 auth 密码
指令进行登录 ,登录成功之后才能执行其他的操作。
并发限制
Redis 默认允许 10000 个客户端同时连接,如果要修改也可以:
快照(RDB)
为了防止 Redis 中的数据丢失,所以会定期向硬盘保存数据。
每次将内存中所有的数据都备份到硬盘 。
AOF
AOF:把数据从内存备份到硬盘。
只把新的数据追回到硬盘。
是否开启:
appendonly on
什么时候触发写硬盘:
always:一修改Redis 同时就写硬盘,(好处:数据不会丢失,缺点:性能慢)
everysec:每秒写硬盘一次,(好处:性能稍微好些,缺点:有可能丢失一秒的数据)
appendfsync always
appendfsync everysec
appendfsync no
扩展:集群方案。
使用不写硬盘数据有可能丢失,如果写硬盘性能会慢,所以这样一个方案。
搭建主从服务器,主服务器完全不写硬盘,从服务器写硬盘。
慢日志
MySQL 中也有慢日志。
慢日志:把执行慢的语句保存到一个日志文件中,然后我们就可以通过查看日志知道网站中哪些功能拖慢网站,然后就可以针对性的优化。
可以配置一个时间 ,当一个指令执行时间超过这个时间 就会记录到慢日志中。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。