Redis学习笔记
Redis数据类型
1.String(字符串) set key value
string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
2.Hash(哈希) hset hash_name key value /hget hash_name key
Redis hash 是一个键值(key=>value)对集合。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
每个 hash 可以存储 232 -1 键值对(40多亿)。
3.List(列表) lpush list_name value (头插)/ lrange list_name startIndex endIndex
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。
4.Set(集合) sadd set_name value/smembers set_name
Redis的Set是string类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
5.zset(sorted set:有序集合) zadd …/zrange zsetname startIndex endIndex withScore
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
Redis事务
注意,redis事务中其中一条语句失败不会发生回滚,也不会使之后的语句执行失败。
可以理解为一个打包好的脚本。
MULTI 标记开始 EXEC 执行
注意!注意!注意! Redis中不提供回滚(Rollback操作)!
Watch
WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),
之后的事务就不会执行。监控一直持续到EXEC命令(事务中的命令是在EXEC之后才执行的,
所以在MULTI命令后可以修改WATCH监控的键值)
比如如下代码
实现一个自增
WATCH mykey
val = GET mykey
val = val + 1
MULTI
SET mykey $val
EXEC
上面代码的思路:
先用Watch监控 mykey。
然后获取mykey的值,加一
通过事务把mykey+1的值赋给mykey
这样如果在exec之前mykey发生了变化,本事务就不会执行。
注意:
Watch只能在被监控的值发生变化的时候阻止事务的执行。执行EXEC(标志事务开始执行)
时就会取消对所有键的监控。或者使用UNWatch取消监控。如果事务不想执行记得取消监控
避免影响下一个事务。
Redis在数据量大时的优化操作
查找以**开头的key
在普通场景下,使用命令
keys pattern
//例 keys n*
则可以查找以 n 开头的所有key
这样做会一次返回所有结果,如果数据量大则会造成卡顿。
**解决方法:**使用游标
scan cursor [match pattern] [Count count]
//例 scan 0 match n* count 10
获取的结果:
需要注意:
结果数量是不可控的,只能大概率符合你所给定的count
游标可能会变小,往回查,所以可能会出现重复数据,需要在逻辑中进行处理,比如使用HashSet去重。
Redis分布式锁
分布式锁要处理的问题:
1.互斥性 在同一时刻,只能有一个客户端获取到锁
2.安全性 锁只能被它的持有者删除
3.避免死锁
4.容错
第一种方式
setNx key value
// 时间复杂度为O(1)
//若key存在,则失败
//若key不存在,则赋值成功
思想:使用如上命令,一个客户端想要进行某某操作,先使用setNx 设置字段为1,如果成功则设置其过期时间,在这段时间内,只有该应用可以进行某某操作。其他客户使用setNx会失败,然后重复获取,知道成功,则进行操作。
while(true){
int status=jedis.setNx("key",1);
if(status ==1) {
jedis.expire("key",5);
//执行操作
}
sleep(200);
}
第二种方式
实现方法同上,把两条redis命令合成一句
set key value [ex seconds] [px milliseconds] [nx|xx]
// nx key不存在才能成功
// xx key存在才能成功
注意:
redis中如果大量key同时过期会导致卡顿。尽量避免,可使用随机值等方法。
Redis异步队列
blpop如果 testlist中没有可pop的数据,则会阻塞,后面的30意思为最长阻塞30秒,如果设置为0则可无限阻塞。
如果有多个客户端阻塞,遵循先阻塞,先服务的原则。
缺点是只能供一个客户端服务。
如果需要供多个客户端使用,可使用下面得订阅者模式。
Redis 订阅者模式
Pub(发送者)/Sub(订阅者):主题订阅者模式
订阅者可以订阅任意数量的频道
Redis持久化
RDB方式
在redis根目录下的配置文件redis.conf中
save 900 1意思为如果在900秒内有1条写入,则备份。以此类推,(ps:使用的是bgsave方式,见后文)
stop-writes-on-bgsave-error yes 意思为当备份进程出错时,主进程就停止写入操作。这样做目的是保护数据持久化的一致性。
如果你的项目中有完善的一致性处理,可以设置为no
rdbcompression yes 意思是在备份后,将rdb进行压缩后保存。可以节省硬盘空间,但是会消耗cpu资源,根据服务器状况选择合适的配置。 在save最后添加 save “” 可以禁用压缩。
Redis手动持久化
SAVE
阻塞Redis服务器进程,将数据备份,知道rdb创建完毕。
BGSAVE
不会阻塞主进程,Fork出一个子进程来创建rdb文件。
Redis自动触发RDB持久化
根据redis.conf里的配置定时触发。(使用的是bgsave)
主从复制时,主节点自动触发。
执行Debug Reload时触发。
执行Shutdown并且没有开启AOF持久化
AOF方式
记录除了查询以外的所有变更数据库记录的指令。
以append形式追加保存到aof文件中。
AOF方式默认是关闭的
改为yes即可生效
always:一旦缓冲区发生变化则将其写入aof文件中
everysec: 每隔一秒写入(默认)
no: 交给操作系统来处理,一般是缓冲区快满的时候进行
区别
rdb是备份数据。 aof是备份数据库收到的指令。
aof优先于rdb文件。
RDB与AOF相结合
http://blog.huangz.me/2017/redis-rdb-aof-mixed-persistence.html