redis是以key-value形式的数据结构所构成的数据库,这里的value又以字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 这几种数据构成,中文官网CRUG网站,英文官网Redis。value的这几种数据类型与java里的几种数据类型类似,操作模式,数据结构几乎一样。
一、数据类型
list:
redis里的list相当于java里的LinkedList、栈、队列,所以还可以像queue一样做栈数据结构类型的操作;
所以除了基本的链表、栈、队列的基本操作还可以用这个特性做下面的操作:
- 替换或更新指定位置的值,如果指定位置没有元素则操作失败
- 给指定位置之前或之后插入值
- 截取指定区间的元素值
- 获取指定位置的元素值
- 移动最后一个元素到另一个list中
set:
set与hash不同的是set不是以键值对存储,并且是无序的,但其实hash也是无序的,只不过hash是以键值对存储,也可以看作map,一般会利用这个特点去存储类似(属性:值)这样的数据,通过已知的属性字段去获取所对应的值,而set是只有key没有值的map,一般会利用key的特性去存储数据,而key是无序的、不可重复的,并且是散列的;
set与list不同的是set是无序的、不可重复的、散列的,而list是有序的可重复集合;
综上redis里的set除了基本的list的增删改,还可以做以下操作:
- 随机抽选一个元素
- 随机抽选指定个数的元素
- 随机删除/移除元素
- 移动一个set中的元素到另一个set中(散列特性,list也可以)
- 获取两个set集合的并集或者交集(不可重复特性)
Zset:
Zset是有序的不可重复的集合,既有list数据类型的特点又有set数据类型的特点,Zset只是在set基础上给每一个元素添加了一个标志性字段,并不是正真的有序,而是用这个绑定的值来当作做有序来做相关的操作;因为还要用到其不可重复性,所以还不能用hash数据类型和list数据类型替代;
可以做以下操作:
- 通过绑定的score字段进行排序并返回排好顺序的列表,可以选择附带score字段的值
- 显示小于或者大于某个区间的元素的列表
- 移除某个区间的元素
hyperloglog:
redis的hyperloglog用来做基数统计的算法,基数统计也可以用set数据类型进行操作但是hyperloglog在这个基础上做了优化,而且hyperloglog集合是可以有重复元素,存储和操作更方便;
优点:只能用内存是固定的,可以统计2^64个不同元素,只需要用12KB的内存,但是有0.18%的错误率,但是可以忽略不计;
bitmaps:
bitmaps位存储,顾名思义这个数据结构是以map形式存储二进制位,map的key可以自行定义,但value只有0和1两个值,来用于统计用户信息,例如统计用户一年的登录次数,某个状态等信息;
二、事务
因为redis是单线程执行的,redis事务的本质是一组队列形式的命令集合,只是在执行过程中会按照命令队列顺序执行,并且在执行过程中,后面被执行的命令不会因为前面命令执行错误而停止并且回滚,相当于一次性、顺序性、排他性的执行一个队列中的一系列命令,因为redis本身就是在内存里的数据库,所以没有持久化,在执行事务的过程中,我们可以在事务结束时选择结束事务或者执行事务,其实只是给redis-server发送一个执行或者不执行这个队列的命令,所以redis事务是没有ADIC原则的。
redis乐观锁
虽然redis事务很鸡肋,但是可以用watch命令用来监视事务执行过程中某个字段值的变化,如果这个值在watch监听开始时和事务命令队列开始执行时有变化则整个事务不会执行,返回nil,执行失败,可以用这个命令来弥补事务原本的原则。
三、持久化
RDB(Redis DataBase):
我们可以配置Redis在n秒内如果超过m个key被修改就自动做快照,下面是默认的快照保存配置(这3个选项都屏蔽,则RDB禁用)∶
# 900秒内如果超过1个key改动,则发起快照保存
save 900 1
# 300秒内如果超过10个key改动,则发起快照保存
save 300 10
# 60秒内如果超过1W个key改动,则发起快照保存
save 60 10000
简而言之,就是在不同的时间点或者设置的时间间隔内,将redis存储的数据生成快照并存储到磁盘等介质上,所以不能完全保证数据的完整性。
RDB是把整个内存数据映射到硬盘中,保存一份到硬盘,因此恢复数据起来比较快,把数据映射回去即可,不像AOF,一条条的执行操作命令。
快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.db。可以通过配置设置自动做快照持久化的方式。
产生快照的情况有以下几种:
手动bgsave执行,非阻塞
手动save执行,阻塞
根据配置文件自动执行(bgsave方式)
客户端发送shutdown,系统会先执行save命令阻塞客户端,然后关闭服务器
当有主从架构时,从服务器向主服务器发送sync命令来执行复制操作时,主服务器会执行bgsaxe操作
RDB工作原理
Redis默认会将快照文件存储在Redis当前进程的工作目录中的dump.rdb文件中,可以通过配置dir和dbfilename两个参数分别指定快照文件的存储路径和文件名。流程过程如下(rdb.c中)。
BGSAVE会fork一个子进程来保存RDB,在这个期间能够正常接受外界命令,这时候如果主进程有修改的语句,就会把需要修改的数据复制出来,给子进程使用,主进程改干嘛干嘛。
保存好的新的RDB后,会将新RDB替换旧的RDB。如果期间还有SAVE,或BGSAVE命令执行,会被拒绝,如果有BGREWRITEAOF命令,会在BGSAVE执行结束后再执行。
AOF(Append Only File):
将redis执行过的所有写指令记录下来,在下次redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了,所以AOF执行起来相对RDB慢一些,但是AOF方式的数据恢复完整度更高。
它也是Redis持久化的重要手段之一,AOF (Append Only File)只追加文件,也就是每次处理完请求命令后都会将此命令追加到aof文件的末尾。而RDB是压缩成二进制等时机开子进程去干这件事。
通过配置进行启动,默认是关闭的。
# 默认appendonly为no
appendonly yes
appendfilename "appendonly.aof"
# RDB文件和AOF文件所在目录
dir /usr/local/redis/data
其实RDB和AOF两种方式也可以同时使用,在这种情况下,如果redis重启的话,则会优先采用AOF方式来进行数据恢复,这是因为AOF方式的数据恢复完整度更高。