一、Redis存储数据类型?
1)、String
字符串类型是Redis最基本的数据类型,它能够存储任何形式的字符串,可以存储用户的信息,JSON化的对象甚至是一张图片。字符串类型是其他四种类型的基础,其他数据类型从某种角度来说只是组织字符串的形式不同,一个字符串类型的键允许存储的最大数据容量是512MB。
赋值命令:SET key value 如果key已经持有其他值,set就复写旧值,无视类型
取值命令:GET key,当键不存在时会返回空。
MSET k1,k2,k3...同时设置多个键值
MGET k1.k2...同时获得多个键值
Redis的所有命令都是原子操作,原子操作即不可拆分的意思,不会在执行的过程中被其他命令插入打断。
2)、List
列表类型可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素。
列表类型内部是使用双向链表实现的,所以向列表两端添加元素的时间复杂度为O(1),使用链表的代价是通过索引访问元素比较慢。借助列表类型。Redis还可以作为队列使用。一个列表类型键最多可以容纳2^32-1个元素。
LPUSH key value1,value2...:向列表左边增加元素,返回值为增加元素 后列表的长度
RPUSH key vaule1,value2...:向列表右边增加元素,返回值为增加元素后列表的长度
LPOP key :从列表左边弹出一个元素。这个命令执行两部操作,第一步是将列表左边的元素从列表中移除,第二步返回被移除的元素值。
RPOP key:从列表右边弹出一个元素
3)、Set
集合中的每个元素都是不同的,且没有顺序,唯一且无序,一个集合类型的键可以存储2^32-1个字符串
集合类型的常用操作是向集合中加入或删除元素,判断某个元素是否存在。
集合类型在Redis内部是使用值为空的hash表来实现的。所以这些操作的时间复杂度都为O(1)
多个集合类型键之间还可以进行并集,交集和差集运算。
SADD key member1,member2...向集合中添加一个或多个元素。如果键不存在则自动创建。返回值是成功加入的元素数量
SREM key member1,member2...从集合中删除一个或多个元素,并返回删除成功的个数。
SMERMBERS key :获取集合中的所有元素。
4)、Hash(散列类型)
hash是一个String类型的field和value的映射表。散列类型适合存储对象。一个散列类型键可以包含2^32-1个字段
HSET key field value:给字段赋值。例如HSET car price 500
HGET key field:获取字段值。例如HGET car price
当HSET执行的是插入操作时(即之前字段不存在)会返回1,当执行的是更新操作时会返回0.还会自动建立。
HMSET key field1 value1 field2 value2...:同时设置多个字段,例如 HMSET car name "bmw" price 5000
HMGET key field1 field2:获得更多字段的值
实际应用:存储博客文章:可以将文章的标题,作者,标签分别放入不同的字段中。
5)、sorted Set (有序集合类型)
在集合类型的基础上有序集合类型为每个元素都关联了一个分数,这使得我们不仅可以完成插入,删除等集合类型的操作,还能够获得分数最高或最低的前n个元素,获取指定分数范围内的元素。虽然集合中的每个元素都是不同的,但是它们的分数可以相同。
二、Redis持久化机制
Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。
实现:单独创建fork()一个子进程,将当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。
RDB:Redis默认的持久化方式,按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制。即Snapshot快照存储,对应产生的数据文件为dump.rdb,通过配置文件中save参数来定义快照的周期。(快照可以是其所表示的数据的一个副本也可以是数据的一个复制品)
AOF:Redis会将每一个收到的写命令都通过Write函数追加到文件最后,类似于MySQL的binlog。当Redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。
三、单线程的Redis为什么这么快
1)纯内存操作
2)单线程操作,避免频繁的上下文切换
3)采用了非阻塞I/O多路复用机制
四、为什么Redis的操作是原子性的,怎么保证原子性的?
对于Redis而言,命令的原子性指的是:一个操作的不可再分,操作要么执行,要么不执行。
Redis的操作之所以是原子性的,是因为Redis是单线程的。
Redis本身提供的所有API都是原子操作,Redis中的事务其实是要保证批量操作的原子性。
多个命令在并发中也是原子性吗?答:不一定,将get和set改成单命令操作,incr.使用Redis的事务,或者使用Redis+Lua==的方式实现。
五、Redis常见性能问题和解决方案
1)Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
2)如果数据比较重要某个Slave开启AOF备份数据,策略设置为每秒同步一次
3)为了主从复制的速度和连接的稳定性,master和Slave最好在同一个局域网内
4)尽量避免在压力很大的主库上增加从库
5)主从复制不要用图状结构,用单向链表结果更为稳定,即Master<-Slave1<-Slave2<-Slave3...
这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。