其他文章链接
Java基础
Java集合
多线程
JVM
MySQL
Redis
docker
计算机网络
操作系统
Redis
1.NoSQL
Not onlt SQL,泛指非关系型数据库。
NoSQL不依赖业务逻辑方式存储,而以简单的key-value模式存储。因此大大的增加了数据库的扩展能力。
- 不遵循SQL标准。
- 不支持ACID。
- 远超于SQL的性能
NoSQL适用场景:
- 对数据高并发的读写
- 海量数据的读写
- 对数据高可扩展性
NoSQL适用场景:
- 需要事务的支持
- 基于sql的结构化查询存储,处理复杂的关系,需要即席查询。
2.Redis与Memcache的不同
串行 vs 多线程+锁( memcached) vs 单线程+多路IO复用(Redis)
(与Memcache三点不同:支持多数据类型,支持持久化,单线程+多路IO复用)
3.Redis概述
- Redis是一个开源的key-value存储系统。
- 默认端口号:6379
- 默认16个数据库,类似数组下标从0开始,初始默认使用0号库。统—密码管理,所有库同样密码。
- 这些数据类型都支持 push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。”
- 在此基础上,Redis支持各种不同方式的排序。
- memcached一样,为了保证效率,数据都是缓存在内存中。区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件。
- 并且在此基础上实现了 master-slave(主从) 同步。
4.Redis应用场景
- 配合关系型数据库做高速缓存
- 多样的数据结构存储持久化数据(手机验证码、认证token等)
5.Redis基本数据类型(5种)
- String(字符串)
- List(链表)
- Set(集合)
- Zset(sorted set 有序集合)
- Hash(哈希类型)
5.1 String
String是Redis最基本的类型(可以理解成与Memcached一模一样的类型),一个key对应一个value。一个Redis中字符串value最多可以是512M。
String类型是二进制安全的,意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象。
数据结构:String的数据结构为简单动态字符串(SimpleDynamicString,缩写SDS)。是可以修改的字符串,内部结构实现上类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。
如图中所示,内部为当前字符串实际分配的空间capacity一般要高于实际字符串长度len。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。 需要注意的是字符串最大长度为512M。
5.2 List
列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
数据结构:快速链表quickList。
首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist(一种特殊双向链表,不像普通的链表使用前后指针关联在一起,它是存储在连续内存上的),也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。
当数据量比较多的时候才会改成quicklist。因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next。Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。
5.3 Set
Set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动去重的,当你需要存储一个列表数据,又不希望出现重复数据时,选择set。
并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
Set是String类型的无序集合。底层是value为null的hash表,所以添加,删除,查找的复杂度都是O(1)。
数据结构:Set数据结构是dict字典,字典是用哈希表实现的。
5.4 Zset
有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合,不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以重复。
因为元素是有序的, 所以可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。访问有序集合的中间元素也是非常快的,因此能够使用有序集合作为一个没有重复成员的智能列表。
数据结构:
SortedSet(zset)是Redis提供的一个非常特别的数据结构,一方面它等价于Java的数据结构Map<String,Double>,可以给每一个元素value赋予一个权重score,另一方面它又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过score的范围来获取元素的列表。
底层使用了两个数据结构:
(1)hash,hash的作用就是关联元素value和权重score,保障value的唯一性,可以通过元素value找到相应的score值。
(2)跳跃表,跳跃表的目的在于给元素value排序,根据score的范围获取元素列表。
拓展:跳跃表(跳表)
从第⒉层开始,1节点比51节点小,向后比较。21节点比51节点小,继续向后比较,后面就是NULL了,所以从21节点向下到第1层。
在第1层,41节点比51节点小,继续向后,61节点比51节点大,所以从41向下。
在第0层,51节点为要查找的节点,节点被找到,共查找4次。
可以看出跳跃表比有序链表效率要高。
5.5 Hash
hash 是一个键值对集合,是一个string类型的field和value的映射表,hash特别适合用于存储对象。类似Java里面的Map<String,Object>。
数据结构:Hash类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当field-value长度较短且个数较少时,使用ziplist,否则使用hashtable。
6.发布和订阅
Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis客户端可以订阅任意数量的频道。
1.客户端可以订阅频道如下图:
2.当给这个频道发布消息后,消息就会发送给订阅的客户端
7.事务
Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。
事务在执行的过程中,不会被其他客户端发送来的命令请求所打断
Redis事务的主要作用就是串联多个命令,防止别的命令插队
7.1 组队、执行
三个命令: Multi、Exec、discard 组队 + 执行
- 从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行
- 直到输入Exec后,Redis会将之前的命令队列中的命令依次执行
- 组队的过程中可以通过discard来放弃组队
事务的错误处理: - 组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消1。(如:set key1 不写value值)
- 如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。(如:set key1 value1; incr key1;)
7.2 锁机制
乐观锁:
- WATCH key:在执行multi之前,先执行watch key1 [key2],可以监视一个(或多个) key ,如果在事务执行之前这些key被其他命令所改动,那么事务将被打断
- Unwatch:取消WATCH命令对所有key的监视。如果在执行WATCH命令之后,执行EXEC命令或DISCARD,不需要再执行UNWATCH
7.3 Redis事务的三个特性
- 单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
- 没有隔离级别的概念:队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行
- 不保证原子性:事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚
8.持久化
Redis 提供了2个不同形式的持久化方式:
- RDB(Redis DataBase):默认保存文件为dump.rdb
- AOF(Append Of File)(默认不开启,配置文件开启):默认保存文件为appendonly.aof
8.1 RDB
RDB:在指定的时间间隔内将内存中的数据集快照写入磁盘,恢复时是将快照文件直接读到内存里。
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件(写时拷贝技术)。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。
Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。
redis.conf中的配置:
save:save时只管保存,其它不管,全部阻塞。手动保存。不建议。
bgsave:Redis会在后台异步进行快照操作, 快照同时还可以响应客户端请求
8.1.1 RDB优点
- 适合大规模数据的恢复
- 对于数据恢复的完整性和一致性不是非常敏感
- 节省磁盘空间
- 恢复速度快
8.1.2 RDB缺点
- Fork 的时候,内存中的数据被克隆了一份,大致⒉倍的膨胀性需要考虑。(空间)
- 虽然 Redis在 fork时使用了写时拷贝技术,但是如果数据庞大时还是比较消耗性能。
- 在备份周期在一定间隔时间做一次备份,所以如果Redis意外down掉的话就会丢失最后一次快照后的所有修改。
9.2 AOF
以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据。换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
9.2.1AOF持久化流程:
- 客户端的请求写命令会被append追加到AOF缓冲区内;
- AOF缓冲区根据AOF持久化策略[always,everysec,no]将操作sync同步到磁盘的AOF文件中;
- AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写(即把多条指令压缩为一条),压缩AOF文件容量。重写的基础大小默认值64M
- Redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的
Redis重启根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
9.2.2 AOF异常恢复
如遇到AOF文件损坏,通过/usr/local/bin/redis-check-aof --fix appendonly.aof命令进行恢复。
9.2.3 AOF同步频率设置
- appendfsync always:始终同步,每次Redis的写入都会立刻记入日志;性能较差但数据完整性比较好
- appendfsync everysec:每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。
- appendfsync no: redis不主动进行同步,把同步时机交给操作系统
9.2.4 AOF优点
- 备份机制更稳健,丢失数据概率更低。
- 可读的日志文本,通过操作AOF稳健,可以处理误操作。
9.2.5 AOF缺点
- 比起RDB占用更多的磁盘空间。(因为比RDB多记录了操作指令)
- 恢复备份速度要慢。(记录东西多恢复就慢)
- 每次读写都同步的话,有一定的性能压力。
- 存在个别 Bug,造成不能恢复。
9.3 AOF和RDB同时开启,redis 听谁的?
AOF和RDB同时开启,系统默认取AOF的数据(数据不会存在丢失)
9.4 AOF和RDB 用哪个
- 官方推荐两个都启用。
- 如果对数据不敏感(允许数据丢失),可以选单独用RDB。
- 不建议单独用 AOF,因为可能会出现Bug。
- 如果只是做纯内存缓存,可以都不用。
10.主从复制
主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制
Master以写为主,Slave以读为主(一主多从)
![](https://i-blog.csdnimg.cn/blog_migrate/45bf279c60d922492bab8beb05bb2c11.png)
10.1作用
- 读写分离,性能扩展
- 容灾快速恢复
10.2 复制原理
- 当从连接上主服务器之后,从服务器向主服务发送进行数据同步消息(sync命令)
- 主服务器接到从服务器发送过来同步消息,把主服务器数据进行持久化,得到rdb文件,把rdb文件发送从服务器,从服务器拿到rdb进行读取
- 每次主服务器进行写操作之后,和从服务器进行数据同步
全量复制:slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
10.3 常用三种方式
10.3.1 一主二仆
- 一个从服务器挂掉(shutdown)后,重启后该从服务器与主服务器的主从关系消失,需要重新输入命令加入主从关系。
- 主服务器挂掉后,重启后还是主服务器,主从关系也还在。
10.3.2 薪火相传
上一个Slave可以是下一个slave的Master,Slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master, 可以有效减轻master的写压力,去中心化降低风险
10.3.3 反客为主
当一个master宕机后,后面的slave可以立刻升为master,其后面的slave不用做任何修改。
用slaveof no one 将从机变为主机(手动)
10.4 哨兵模式(sentinel)
反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
![](https://i-blog.csdnimg.cn/blog_migrate/776378b8c7e1b8cc093eb98798d62d26.png)
10.4.1 配置哨兵过程
- 自定义的/myredis目录下,新建sentinel.conf 文件,名字绝不能错
- 配置哨兵,填写内容
sentinel monitor mymaster 127.0.0.1 6379 1
其中mymaster为监控对象起的服务器名称,1为至少有多少个哨兵同意迁移的数量。 - 启动哨兵
- 当主机挂掉,从机选举产生新的主机(原主机重启后会变为从机)。
10.4.2 从机会被选举为主机的条件
依次:
- 选择优先级靠前的 默认slave-priority 100(越小优先级越高)
- 选择偏移量最大的(偏移量是指获得原主机数据最全的)
- 选择runid最小的从服务 每个redis(实例启动后都会随机生成一个40位的runid)
10.4.3 复制延时(哨兵模式缺点)
由于所有的写操作都是先在Master上操作,然后同步更新到slave上,所以从Master同步到slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。
11.集群
为解决容量不够和并发写操作,以前通过代理主机来解决,redis3.0中提供了无中心化集群配置。
无中心化:任何一台服务器都可以作为集群的入口,服务器之间可以互相连通
Redis集群实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N。
Redis集群通过分区来提供一定程度的可用性(availability):即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。
一个集群至少要有三个主节点
选项–cluster-replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
分配原则尽量保证每个主数据库运行在不同的IP地址,每个从库和主库不在一个IP地址上
Slots:
一个 Redis 集群包含16384个插槽, 数据库中的每个键都属于16384 插槽的其中一个,
集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。集群中的每个节点负责处理一部分插槽。
举个例子, 如果一个集群可以有主节点, 其中:
- 节点 A 负责处理 0 号至 5460 号插槽。
- 节点 B 负责处理 5461 号至 10922 号插槽。
- 节点 C 负责处理 10923 号至 16383 号插槽。
在redis-cli每次录入、查询键值,redis都会计算出该key应该送往的插槽,如果不是该客户
端对应服务器的插槽,redis会报错,并告知应前往的redis实例地址和端口。
redis-cli客户端提供了–c 参数实现自动重定向
如 redis-cli -c–p 6379 登入后,再录入、查询键值对可以自动重定向
不在一个slot下的键值,是不能使用mget,mset等多键操作
如果所有某一段插槽的主从节点都宕掉,redis服务是否还能继续?
cluster-require-full-coverage 为yes ,整个集群都挂掉
cluster-require-full-coverage 为no ,该插槽数据全都不能使用,也无法存储。
由redis.conf中的参数 cluster-require-full-coverage决定
优点:实现扩容;分摊压力;无中心配置相对简单
缺点:多键操作是不被支持的, Lua脚本不支持
12 缓存问题
12.1 缓存穿透
缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。(比如:出现很多非正常、不存在的url访问)
解决方案:
- 对空值缓存:如果一个查询返回的数据为空,仍然把null进行缓存,设置空结果的过期时间会很短,最长不超过五分钟。(空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间,如果是攻击,问题更严重。比较有效的方法是针对这类数据设置一个较短的过期时间,让其自动剔除)
- 设置可访问的名单(白名单):使用bitmaps类型定义一个可以访问的名单,名单id作为 bitmaps的偏移量,每次访问和 bitmap里面的id进行比较,如果访问id不在bitmaps里面,进行拦截,不允许访问。
- 布隆过滤器:对所有可能查询的数据以hash形式存储,在控制层先进行校验,不符合则丢弃。
- 进行实时监控:当发现Redis的命中率开始急速降低,需要排查访问对象和访问的数据,和运维人员配合,可以设置黑名单限制服务。
12.2 缓存击穿
缓存击穿:一个高频的key过期,恰好在这个时间点对这个Key有大量的并发请求过来。
解决方案:
- 把热门数据提前放到redis里面,并加长热门数据key的过期时长。
- 维护一个定时任务,将快要过期的key重新设置。
- 可以使用分布式锁,当在缓存中拿不到数据时,使用分布式锁去数据库中拿到数据后,重新设置到缓存。
- 队列:只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,直接走缓存。
12.3 缓存雪崩
缓存雪崩:极短时间内,大量的key的集中过期情况,所有的查询都落在数据库上。
解决方案:
- 保证redis的高可用,可以使用主从+哨兵或redis集群,避免服务器不可用
- 二级/多级缓存:当redis查询不到结果,可以从本地缓存中查询,如果还是查不到,就要从数据库中查询。
- 使用锁或队列:用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。不适用高并发情况。
- 设置缓存时间:需要给redis缓存中的key值设置过期时间时,尽量不要设置同一时间,如果业务场景允许可以将缓存时间加个随机数。
- 设置过期标志更新缓存:记录缓存数据是否过期(设置提前量),如果过期会触发通知另外的线程在后台去更新实际key的缓存。
13.分布式锁
分布式锁解决问题:跨JVM的互斥机制来控制共享资源的访问
13.1 分布式锁实现方式
- 基于数据库实现分布式锁
- 基于缓存(Redis等)
- 基于Zookeeper
每一种分布式锁解决方案都有各自的优缺点:性能:redis最高; 可靠性:zookeeper最高。
13.2 基于redis实现分布式锁
setnx 命令:
setnx key value 加锁, del key释放锁 del users
expire key seconds:设置过期时间,自动释放 expire users 12
加锁和过期时间不是原子性操作
原子性操作:set keys values nx ex 12 (上锁的同时设置过期时间)
13.3 存在问题
可能会释放其他服务器的锁。
解决:setnx获取锁时,设置一个指定的唯一值(例如: uuid;释放前获取这个值,判断是否自己的锁。
保证删除的原子性:lua脚本
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
13.4 为了确保分布式锁可用,至少要确保锁的实现同时满足以下四个条件:
- 互斥性。在任意时刻,只有一个客户端能持有锁。
- 不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
- 解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。
- 加锁和解锁必须具有原子性。
附:Redis命令
Linux下
- redis-server redis.conf 启动redis服务
- redis-cli -p 端口号 连接redis
- redis-cli -c -p 端口号 以集群方式连接redis
键(Key)
- keys * 查看当前库所有key(匹配:keys*1)
- exists key 判断某个key是否存在
- type key 查看你的 key是什么类型(返回1/0)
- del key 删除指定的key数据
- unlink key 根据value选择非阻塞删除(仅将keys 从 keyspace元数据中删除,真正的删除会在后续异步操作。)
- expire key 10 为给定的 key设置过期时间为10s
- ttl key 查看还有多少秒过期,-1表示永不过期,-2表示已过期。
- select 8 切换到8数据库
- dbsize 查看当前数据库的key的数量
- flushdb 清空当前库
- flushall 通杀全部库
String
- set <key> <value> 添加键值对
- setnx <key> <value> 只有在key不存在时设置key的值
- get <key> 查询对应键值
- append <key> <value> 将给定的value追加到原值的末尾
- strlen <key> 获得值的长度
- incr <key> 将key中储存的数字值增1(只能对数字值操作,如果为空,新增值为1)
- decr <key> 将key中储存的数字值减1(只能对数字值操作,如果为空,新增值为-1)
- incrby/decrby <key> <步长> 将key中储存的数字值增减。自定义步长。
- mset <key1> <value1> <key2> <value2> 同时设置一个或多个 key-value对
- mget <key1> <key2> <key3> 同时获取一个或多个 value
- msetnx <key1> <value1> <key2> <value2> 设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在(原子性,有一个失败则都失败)
- getrange <key> <起始位置> <结束位置> 获得值的范围,类似java中的substring()
- setrange <key> <起始位置> <value> 用 value覆写key所储存的字符串值,从<起始位置>开始(从0开始)
- setex <key> <过期时间> 设置键值的同时,设置过期时间,单位秒
- getset <key> <value> 以新换旧,设置了新值同时获得旧值
List
- lpush/rpush <key> <value1> <value2> <value3> 从左边/右边插入一个或多个值
- lpop/rpop <key> 从左边/右边吐出一个值(值在键在,值光键亡)
- rpoplpush <key1> <key2> 从key1列表右边吐出一个值,插到key2列表左边。
- lrange <key> <start> <stop> 按照索引下标获得元素(从左到右)
- lrange mylist 0 -1 (0代表左边第一个,-1代表右边第一个),获得mylist所有元素
- lindex <key> <index> 按照索引下标获得元素(从左到右)
- llen <key> 获得列表长度
- linsert <key> before/after <value> <newvalue> 在value的前面/后面插入newvalue
- lrem <key> <n> <value> 从左边删除前n个value(从左到右)
- lset <key> <index> <value> 将列表key下标为index的值替换成value
Set
- sadd <key> <value1> <value2> 将一个或多个 member 元素加入到集合key 中,已经存在的member元素将被忽略
- smembers <key> 取出该集合的所有值
- sismember <key> <value> 判断集合key是否为含有该value值,有1,没有0
- scard <key> 返回该集合的元素个数
- srem <key> <value1> <value2> … 删除集合中的某个(些)元素
- spop <key> 随机从该集合中吐出一个值
- srandmember <key> <n> 随机从该集合中取出n个值。不会从集合中删除
- smove <source> <destination> value把集合中一个值从一个集合移动到另一个集合
- sinter <key1> <key2> 返回两个集合的交集元素
- sunion <key1> <key2> 返回两个集合的并集元素
- sdiff <key1> <key2> 返回两个集合的差集元素(key1中的,不包含key2中的)
Zset
- zadd <key> <score1> <value1> <score2> <value2> 将一个或多个member元素及其score 值加入到有序集key当中
- zrange <key> <start> <stop> [WITHSCORES] 返回有序集 key 中,下标在start、stop之间的元素带。WITHSCORES,可以让分数一起和值返回到结果集
- zrangebyscore key min max [withscores] 返回有序集key中,所有score 值介于min和max之间(包括等于)的成员。有序集成员按score值递增(从小到大)次序排列
- zrev rangebyscore key max min [withscores] 同上,改为从大到小排列
- zincrby <key> <increment> <value> 为元素的score加上增量
- zrem <key> <value> 删除该集合下,指定值的元素
- zcount <key> <min> <max> 统计该集合,分数区间内的元素个数
- zrank <key> <value> 返回该值在集合中的排名,从0开始
Hash
- hset <key> <field> <value> <key> 集合中的 field键赋值value
- hget <key1> <field> 从key1集合field取出 value
- hmset <key1> <field1> <value1> <field2> <value2>… 批量设置hash的值
- hexists <key1> <field> 查看哈希表 key 中,给定域 field 是否存在。
- hkeys <key> 列出该hash集合的所有field
- hvals <key> 列出该hash集合的所有value
- hincrby <key> <field> <increment> 为哈希表 key 中的域 field 的值加上增量 1 -1
- Hsetnx <key> <field> <value> 将哈希表 key 中的域 field 的值设置为value ,当且仅当field 不存在
发布订阅
- SUBSCRIBE channel1 订阅channel1频道
- publish channel1 hello 给channel1发布消息hello
事务
- Multi:从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行
- Exec:直到输入Exec后,Redis会将之前的命令队列中的命令依次执行
- discard:组队的过程中可以通过discard来放弃组队
- WATCH key:在执行multi之前,先执行watch key1 [key2],可以监视一个(或多个) key ,如果在事务执行之前这些key被其他命令所改动,那么事务将被打断
- Unwatch:取消WATCH命令对所有key的监视。如果在执行WATCH命令之后,执行EXEC命令或DISCARD,不需要再执行UNWATCH
持久化
- /usr/local/bin/redis-check-aof --fix appendonly.aof 如遇到AOF文件损坏,通过此命令可进行恢复。
主从复制
- slaveof <ip> <port> 在从服务器redis下输入该命令,成为某个实例(主服务器)的从服务器
- info replication 查看节点信息
分布式锁
- setnx key value 加锁,
- del key 释放锁(如:del users)
- expire key seconds:设置过期时间,自动释放(如:expire users 12 )
- set keys values nx ex 12 上锁的同时设置过期时间