Redis笔记
redis介绍
redis数据存储格式
- redis自身是一个map,数据采用key :value存储
- 数据类型指的是存储的数据的类型,也就是 value 部分的类型,key 部分永远都是字符串
key
删除指定key
- DEL key
# 设置一个key
127.0.0.1:6379> SET name zhangsan
OK
# 获取key
127.0.0.1:6379> get name
"zhangsan"
# 删除key
127.0.0.1:6379> DEL name
(integer) 1
# 在进行获取,发现对应key为(nil)
127.0.0.1:6379> GET name
(nil)
判断key是否存在
- EXISTS key
# 设置一个key
127.0.0.1:6379> SET name zhangsan
OK
# 判断是否存在,返回1表示存在
127.0.0.1:6379> EXISTS name
(integer) 1
# 将key删除
127.0.0.1:6379> DEL name
(integer) 1
# 在进行判断,发现返回0,表示不存在
127.0.0.1:6379> EXISTS name
(integer) 0
获取当前数据库所有key
- KEYS *
- * 匹配任意数量的任意符号
- ? 配合一个任意符号
- [符号] 匹配一个指定符号
# 查看所有的key
127.0.0.1:6379> keys *
1) "users"
2) "list1"
3) "id:001"
4) "id:oo2"
5) "list2"
为给定的key设置过期时间
- EXPIRE key 秒数
# 设置name5秒后过期
127.0.0.1:6379> EXPIRE name 5
(integer) 1
# 5秒之内正常获取
127.0.0.1:6379> get name
"zhansgan"
# 5秒之后,对应key失效被删除,获取为空
127.0.0.1:6379> get name
(nil)
- PEXPIRE key 毫秒数
# 设置name5000毫秒后数据过期
127.0.0.1:6379> PEXPIRE name 5000
(integer) 1
# 5秒内正常获取
127.0.0.1:6379> get name
"zhangsan"
# 5秒之后获取失败
127.0.0.1:6379> get name
(nil)
- EXPIREAT key 时间戳
# 使用方法同上,只不过传入的是时间戳
EXPIRAT key 7985455
将key移动到指定数据库
-
redis默认16个数据库
-
MOVE key 数据库编号
# 将当前数据库的name移动到1号数据库
127.0.0.1:6379> MOVE name 1
(integer) 1
# 尝试获取为空
127.0.0.1:6379> GET name
(nil)
# 切换到1号数据库
127.0.0.1:6379> SELECT 1
OK
# 成功获取到
127.0.0.1:6379[1]> GET name
"zhangsan"
移除指定key的过期时间
- PERSIST key
# 设置一个key
127.0.0.1:6379> SET name zhangsan
OK
# 设置过期时间
127.0.0.1:6379> PEXPIRE name 5000
(integer) 1
# 移除过期时间
127.0.0.1:6379> PERSIST name
(integer) 1
# 5秒后获取,还是存在
127.0.0.1:6379> get name
"zhangsan"
获取指定key还有多少秒过期
- PTTL key【以毫秒返回】
# 设置过期时间127.0.0.1:6379> PEXPIRE name 5000(integer) 1# 获取距离过期时间还有多久127.0.0.1:6379> PTTL name(integer) 2046
- TTL key【以秒数返回】
# 设置过期时间127.0.0.1:6379> EXPIRE name 5(integer) 1# 获取过期时间,负数代表已经过期127.0.0.1:6379> TTL name(integer) -2
获取当前数据库随机一个key
- RANDOMKEY
# 获取随机key127.0.0.1:6379> RANDOMKEY"sex"127.0.0.1:6379> RANDOMKEY"name"
为指定key重新命名
- RENAME key 新名称【为key设置一个新名称,不管新名称是否已存在】
# 注意:当key的新名称数据库已经存在时,将会覆盖已存在的值# 设置一个key127.0.0.1:6379> set name zhangsanOK# 修改名称127.0.0.1:6379> RENAME name my-nameOK# 查看key,发现key的名称已近修改127.0.0.1:6379> keys *1) "sex"2) "age"3) "my-name"# 使用新的key获取,成功获取到127.0.0.1:6379> get my-name"zhangsan"
- RENAMEEX key 新名称【当新名称不存在时设置为新名称】
# 设置两个key127.0.0.1:6379> set name zhangsanOK127.0.0.1:6379> set my-name lisiOK# 将name重新命名为my-name,注意my-name已近存在,所以会设置失败127.0.0.1:6379> RENAMENX name my-name(integer) 0
序列化key
- DUMP name
# 序列化,成功返回序列化的值,失败为(nil)127.0.0.1:6379> DUMP name"\x00\bzhangsan\t\x00\xa7\xce\xa1\xe9\xcc\xbeE\xf9"
获取key的类型
- TYPE key
# 获取name的类型,返回string127.0.0.1:6379> TYPE namestring
string
设置key的值
- SET key value
127.0.0.1:6379> set name zhangsongOK
获取key的值
- GET key
127.0.0.1:6379> GET name"zhansgan"
截取字符串
- GETRANGE key 开始索引 ( 0开始 ) 结束索引【左闭右开】
# 设置key127.0.0.1:6379> SET name zhansgongOK# 截取字符串127.0.0.1:6379> GETRANGE name 0 4"zhans"
获取key的值并返回旧值
- GETSET key value
# 设置新的值并返回旧的值127.0.0.1:6379> GETSET name lisi"zhansgong"# 获取新值127.0.0.1:6379> GET name"lisi"
批量获取key的值
- MGET key1 key2…
# 设置两个key127.0.0.1:6379> SET name zhangsnaOK127.0.0.1:6379> set age 19OK# 获取数据,不存在返回(nil)127.0.0.1:6379> MGET nam age1) (nil)2) "19"127.0.0.1:6379> MGET name age1) "zhangsna"2) "19"
获取指定key value的偏移量上的位
- GETBIT key【redis会将字符串转为ASCII,然后转为二进制,我们获取的值就是对应位上的0,1】
# 我们设置一个key的value为a,a的二进制为01100001127.0.0.1:6379> SET name aOK# 获取第一位为0127.0.0.1:6379> GETBIT name 0(integer) 0# 获取第三位也是对的127.0.0.1:6379> GETBIT name 2(integer) 1
设置指定key value上偏移量的位
- SETBIT key 偏移量 值
# 设置key的值为a127.0.0.1:6379> SET name aOK127.0.0.1:6379> GET name"a"# 设置字符串的位127.0.0.1:6379> SETBIT name 6 1(integer) 0127.0.0.1:6379> SETBIT name 7 0(integer) 1# 获取数据,可以发现数据已经改变127.0.0.1:6379> get name"b"
设置key的值并且设置过期时间
- SETEX key 秒数 value【以秒为单位】
# 设置name值为zhansgan,并且5秒后过期127.0.0.1:6379> SETEX name 5 zhangsanOK127.0.0.1:6379> TTL name(integer) 3127.0.0.1:6379> TTL name(integer) -2
- PSETEX key 毫秒数 【以毫秒为单位】
# 设置name5000毫秒过期127.0.0.1:6379> PSETEX name 5000 zhangsanOK127.0.0.1:6379> TTL name(integer) 3
当key不存在时设置值
- SETNX key value
# 当值不存在成功127.0.0.1:6379> SETNX name zhansgan(integer) 1# key已存在失败127.0.0.1:6379> SETNX name lisi(integer) 0
设置对应key的value上指定索引的值
- SETRANGE key 索引位 value
# 设置key127.0.0.1:6379> SET name zhangsanOK# 设置name的索引位0上的值为b127.0.0.1:6379> SETRANGE name 0 b(integer) 8# 获取,修改成功127.0.0.1:6379> get name"bhangsan"
获取指定key的value的长度
- STRLEN key
# 设置key127.0.0.1:6379> SET name zhangsanOK# 获取长度127.0.0.1:6379> STRLEN name(integer) 8
批量设置key的值
- MSET key1 value1 key2 value2…
# 批量设置key127.0.0.1:6379> MSET name zhansgan age 19 weight 104 height 180OK# 查看,修改成功127.0.0.1:6379> MGET name age weight height1) "zhansgan"2) "19"3) "104"4) "180"
当对应key不存在时修改值
- MSETNX key1 value1 key2 value2…
# 设置name值,因为name已存在所以设置失败127.0.0.1:6379> MSETNX name lisi(integer) 0127.0.0.1:6379> get name"zhansgan"
将key的值自增
- INCR key【自增1】
127.0.0.1:6379> SET age 12OK# 将age自增,默认加1127.0.0.1:6379> INCR age(integer) 13127.0.0.1:6379> get age"13"
- INCRBY key value【为key自增指定的值】
# 为key自增10127.0.0.1:6379> INCRBY age 10(integer) 23
- INCRFLOAT key value【为key自增指定的浮点数】
# 为key自增1.2127.0.0.1:6379> INCRBYFLOAT age 1.2"24.2"
将key的值自减
- DECR key【减1】
# 自减1127.0.0.1:6379> DECR age(integer) 19
- DECRBY key value【减去指定值】
# 自减10127.0.0.1:6379> DECRBY age 10(integer) 9
向key的值追加字符
- APPEND key value
# 设置key127.0.0.1:6379> SET name zhansganOK# 向key追加值127.0.0.1:6379> APPEND name 123(integer) 11# 获取127.0.0.1:6379> get name"zhansgan123"
hash
定义
- hash底层使用hash表存储,Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象
- Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)
- 如果field比较少,底层使用类数组存储
- 如果field数量比较多,底层使用HashMap存储
删除一个或多个哈希字段
- HDEL key field1 filed2…
# 设置user下两个field127.0.0.1:6379> HSET user name zhangsan(integer) 1127.0.0.1:6379> HSET user age 12(integer) 1# 删除field127.0.0.1:6379> HDEL user name age(integer) 2
查看所选key是否存在对应的field
- HEXISTS key file
# 为user设置一个field为name127.0.0.1:6379> HSET user name zhangsan(integer) 1# 判断是name否存在,可以看到存在127.0.0.1:6379> HEXISTS user name(integer) 1# 判断age是否存在,可以发现不存在127.0.0.1:6379> HEXISTS user age(integer) 0
获取哈希指定的field
- HGET key field
# 获取user的name字段127.0.0.1:6379> HGET user name"zhangsan"
获取hash所有的字段和值
- HGETALL key
# 向hash存入数据127.0.0.1:6379> HSET user name zhansgan(integer) 1127.0.0.1:6379> HSET user age 14(integer) 1# 获取所有字段127.0.0.1:6379> HGETALL user1) "name"2) "zhansgan"3) "age"4) "14"
为hash指定field自增指定值
- HINCREBY key field 自增值
# 为user下的age字段自增10127.0.0.1:6379> HINCRBY user age 10(integer) 24
- HINCREBYFLOAT key field 自增值【自增浮点数】
# 为user下age字段自增1.2127.0.0.1:6379> HINCRBYFLOAT user age 1.2"25.2"
获取hash所有字段
- HKEYS key
# 获取user所有的field127.0.0.1:6379> HKEYS user1) "name"2) "age"
批量获取hash的field值
- HMGET key field1 field2…
# 获取user的name,age字段值127.0.0.1:6379> HMGET user name age1) "zhansgan"2) "25.2"
获取hash的field数量
- HLEN key
# 获取user的数量127.0.0.1:6379> HLEN user(integer) 2
批量设置hash的field和值【redis4.0已经弃用,推荐使用HSET】
- HMSET key fiel1 value1 field2 value2…
# 设置user的name为zhangsan,age为19127.0.0.1:6379> HMSET user name zhangsan age 19OK# 使用HSET也可以设置多个127.0.0.1:6379> HSET user name zhansgan age 19(integer) 0
当hash字段不存在时设置field
- HSETNX key field value
# 当user下不存在name时设置值为zhangsan127.0.0.1:6379> HSETNX user name zhasngan(integer) 0
获取hash所有的field的值
- HVALS key
# 获取user下所有key的值127.0.0.1:6379> HVALS user1) "zhansgan"2) "19"
迭代hash的键值对
- SCAN key 游标 匹配规则 查询数量
- 会默认返回两个元组,第一个返回用于下一次迭代的下标。第二个为迭代出来的元组
127.0.0.1:6379> HSET user name zhansgan age 19 weight 100 height 180(integer) 0# 迭代user中的值包含n的值127.0.0.1:6379> HSCAN user 0 match 'n*'1) "0"2) 1) "name" 2) "zhansgan"
注意事项
- hash类型下只能存放字符串,这是可能有人问了:我存入一个2不是还可以进行自增运算吗?注意,这是redis在底层将字符串转为了数字进行计算,理论上还是存储的为字符串
- hash不存在嵌套模式,hash一个field只能存入string。如果数据为获取到为(nil)
- hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用
- 尽量避免使用HGETALL,如果hash内部field属性过多,这将会是hash速度的瓶颈
list
介绍
- Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
- 一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)
移除列表并返回列表第一个元素,阻塞操作
- BLPOP key 超时时间
- 如果列表不存在元素或列表不存在,会阻塞设置的时间,在此时间内,列表添加了元素将会进行删除
BLPOP lisi 601) "lisi"2) "1"(12.31s)
移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
- BRPOP key1 key2… 超时时间
从列表弹出一个值,将弹出的值加入到另一个列表,指定时间后失败
- BRPOPLPUSH key1 key2 超时时间
# 向name中添加值127.0.0.1:6379> LPUSH name zhansgan lisi wangwu zhaopliu(integer) 4# 向name2添加一个值127.0.0.1:6379> LPUSH name2 lisi(integer) 1# 进行弹出加入到name1中127.0.0.1:6379> BRPOPLPUSH name name1 5"zhansgan"# 查看name值127.0.0.1:6379> LRANGE name 0 -11) "zhaopliu"2) "wangwu"3) "lisi"# 查看name1值127.0.0.1:6379> LRANGE name1 0 -11) "zhansgan"
根据索引获取指定列表的value
- LINDEX key index
# 获取name列表0索引上的value127.0.0.1:6379> LINDEX name 0"zhaopliu"
在列表指定元素前面或后面插入元素
- LINSERT key BEFORE或AFTER 指定的元素 插入的元素
# 向name列表添加一个元素127.0.0.1:6379> LPUSH name zhangsan(integer) 1# 在name列表的zhangsan元素前插入值wangwu127.0.0.1:6379> LINSERT name BEFORE zhangsan wangwu(integer) 2# 进行查看127.0.0.1:6379> LRANGE name 0 -11) "wangwu"2) "zhangsan"
获取列表长度
- LLEN key
# 获取name的长度127.0.0.1:6379> LLEN name(integer) 2
从左边弹出列表指定个元素
- LPOP key count
# 弹出列表name2个元素127.0.0.1:6379> LPOP name 21) "wangwu"2) "zhangsan"
从右边弹出列表指定个元素
- RPOP key count
# 从右边弹出name3个元素,如果不存在会只弹出存在的127.0.0.1:6379> RPOP name 31) "zhangsan"
从左边添加一个元素
- LPUSH key value
# 从name列表左边加入一个zhangsan127.0.0.1:6379> LPUSH name zhangsan(integer) 1# 查看列表127.0.0.1:6379> LRANGE name 0 -11) "zhangsan"
当列表存在时添加元素
- LPUSHX key value【只有列表存在才添加,LPUSH当列表不存在会创建列表】
# 因为age不存在,所以添加失败127.0.0.1:6379> LPUSHX age 12(integer) 0
获取列表指定范围的元素
- LRANGE key begin end【-1代表最后一个】
# 获取name列表所有元素127.0.0.1:6379> LRANGE name 0 -11) "zhangsan"2) "zhangsan"
删除列表元素
- LREM key count 元素【可能会有人问,为什么要指定删除数量。因为列表可能会含有重复的元素,所以需要指定删除数量】
# 添加元素127.0.0.1:6379> LPUSH name zhangsan lisi(integer) 2# 查看,添加成功127.0.0.1:6379> LRANGE name 0 -11) "lisi"2) "zhangsan"# 删除1个zhangsan127.0.0.1:6379> LREM name 1 zhangsan(integer) 1# 查看,删除成功127.0.0.1:6379> LRANGE name 0 -11) "lisi"
修改列表指定下标的元素
- LSET key index value
# 进行元素的添加127.0.0.1:6379> LPUSH name zhangsan lisi wangwu(integer) 3# 修改name列表第一个元素为zhaoliu127.0.0.1:6379> LSET name 0 zhaoliuOK# 查看列表,修改成功127.0.0.1:6379> LRANGE name 0 -11) "zhaoliu"2) "lisi"3) "zhangsan"
保留列表指定区域的元素
- LTRIM key begin end
# 添加元素127.0.0.1:6379> LPUSH name zhangsan wangwu lisi zhaoliu hanqi(integer) 5# 查看,添加成功127.0.0.1:6379> LRANGE name 0 -11) "hanqi"2) "zhaoliu"3) "lisi"4) "wangwu"5) "zhangsan"# 保留下标1到2的元素127.0.0.1:6379> LTRIM name 1 2OK# 查看,修改成功127.0.0.1:6379> LRANGE name 0 -11) "zhaoliu"2) "lisi"
从右边弹出指定个元素
- RPOP key count
# 添加元素127.0.0.1:6379> RPUSH name zhangsan lisi wangwui zhaoliu(integer) 4# 查看,添加成功127.0.0.1:6379> LRANGE name 0 -11) "zhangsan"2) "lisi"3) "wangwui"4) "zhaoliu"# 删除name右边以一个元素127.0.0.1:6379> RPOP name 11) "zhaoliu"
从右边弹出一个元素加入到指定列表中
- RPOPLPUSH list1 list2
# 进行弹出127.0.0.1:6379> RPOPLPUSH name name1"wangwui"# 查看列表127.0.0.1:6379> LRANGE name1 0 -11) "wangwui"127.0.0.1:6379> LRANGE name 0 -11) "zhangsan"2) "lisi"
从右边弹出指定个元素
- RPOP key count
# 添加元素127.0.0.1:6379> LPUSH name zhangsan lisi(integer) 2# 从name右边弹出一个元素127.0.0.1:6379> RPOP name 11) "zhangsan"
从右边添加元素
- RPUSH key value
# 从name右边天啊及zhangsan127.0.0.1:6379> RPUSH name zhansgan(integer) 2
- RPUSHX key value【列表不存在添加失败,不会新创建列表】
# 如果lisi列表存在,进行元素的添加,不会创建新的列表127.0.0.1:6379> RPUSHX lisi 1(integer) 0
set
定义
- 与hash存储结构完全相同,仅存储键,不存储值(nil),并且值是不允许重复的
- 集合因为是hash所以它是无序的
向集合添加一个或多个元素
- SADD key value1 value2…
# 添加元素,我们添加的有重复的,如果是列表将会有两个wangwu127.0.0.1:6379> SADD name zhangsan lisi wangwu wangwu(integer) 3# 查看set127.0.0.1:6379> SMEMBERS name1) "lisi"2) "wangwu"3) "zhangsan"
查看集合元素数量
- SCARD key
# 查看name集合元素数量127.0.0.1:6379> SCARD name(integer) 3
查看集合与另一个集合的差集
- SDIFF key1 key2
# 集合1127.0.0.1:6379> SADD num 1 2 3(integer) 3# 集合2127.0.0.1:6379> SADD num2 3 4 5(integer) 3# 它们之间的差分127.0.0.1:6379> SDIFF num num21) "1"2) "2"
查看集合与其他集合的交集
- SINTER key1 key2…
# 集合1127.0.0.1:6379> SADD num 1 2 3 4 5 6 (integer) 6# 集合2127.0.0.1:6379> SADD num2 2 3 9(integer) 3# 查看两个集合的交集127.0.0.1:6379> SINTER num num21) "2"2) "3"
将一个集合的交集存入另一个集合
- SINTERSTORE 存入的集合 key1 key2
# 集合1127.0.0.1:6379> SADD num 1 2 3(integer) 3# 集合2127.0.0.1:6379> SADD num2 2 3 4 5(integer) 4# 查出num和num2的交集,并将他们存放到num3中127.0.0.1:6379> SINTERSTORE num3 num num2(integer) 2# 查看num3从,存放成功127.0.0.1:6379> SMEMBERS num31) "2"2) "3"
判断元素是否存在与集合中
- SISMEMBER key value
# 查看11是否存在于num中127.0.0.1:6379> SISMEMBER num 11(integer) 0
查看集合所有元素
- SMEMBERS key
# 查看num集合中所有元素127.0.0.1:6379> SMEMBERS num1) "1"2) "2"3) "3"
将一个集合的元素移动到另一个集合中
- SMOVE 移动的集合 目标集合 元素
# 向集合添加元素127.0.0.1:6379> SADD name zhansgan lisi(integer) 2# 将name集合中lisi元素移动到name1中127.0.0.1:6379> SMOVE name name1 lisi(integer) 1# 查看name1的元素127.0.0.1:6379> SMEMBERS name11) "lisi"# 查看name的元素127.0.0.1:6379> SMEMBERS name1) "zhansgan"
随机删除集合一个元素
- SPOP key
# 从name随机删除一个元素127.0.0.1:6379> SPOP name"zhansgan"
随机返回集合指定个元素
- SRANDMEMBER key count
# 从name随机获取2个元素,可以发现每次都是随机的127.0.0.1:6379> SRANDMEMBER name 21) "zhansgan"2) "lisi"127.0.0.1:6379> SRANDMEMBER name 21) "zhansgan"2) "wangwu"
删除集合多个元素
- SREM key value1 value2…
# 删除name集合两个元素127.0.0.1:6379> SREM name zhangsan lisi(integer) 1# 查看,删除成功127.0.0.1:6379> SMEMBERS name1) "zhansgan"2) "wangwu"
返回一个集合与其他集合的并集
- SUNION key1 key2…
# 设置两个集合127.0.0.1:6379> SADD name zhangsan(integer) 1127.0.0.1:6379> SADD name1 lisi(integer) 1# 获取并集127.0.0.1:6379> SUNION name name11) "lisi"2) "zhangsan"
将一个集合与其他集合的并集放入另一个集合
- SUNIONSTORE 目标集合 集合1 集合2…
# 将name和name1的并集放入name3127.0.0.1:6379> SUNIONSTORE name3 name name1(integer) 3# 查看,成功127.0.0.1:6379> SMEMBERS name31) "lisi"2) "lsii"3) "zhangsan"
迭代集合的属性
- SSCAN key 迭代的游标 match 匹配规则 次数
# 迭代集合name的所有元素127.0.0.1:6379> SSCAN name 0 match "*"1) "0"2) 1) "lsii" 2) "zhangsan"
sorted set
定义
-
可以排序的集合
-
Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
向有序集合添加元素
- ZADD key score1 number2 score2 number2…
# 向name集合添加zhangsan和wangwu并添加分数127.0.0.1:6379> ZADD name 1 zhangsan 2 wangwu(integer) 2127.0.0.1:6379> ZRANGE name 0 -11) "zhangsan"2) "wangwu"
获取集合元素数量
- ZCARD key
# 获取name的元素数量127.0.0.1:6379> ZCARD name(integer) 2
获取指定分数内的元素数量
- ZCOUNT key min max
# 获取name分数为2到3127.0.0.1:6379> ZCOUNT name 2 3(integer) 2
将集合指定元素的分数自增
- ZINCRBY key 自增数 元素
# 设置元素127.0.0.1:6379> ZADD name 1 age(integer) 1# 将name集合中的age分数自增10127.0.0.1:6379> ZINCRBY name 10 age"11"# 查看元素分数127.0.0.1:6379> ZRANGE name 0 -1 withscores1) "age"2) "11"
将多个集合的交集放入另一个集合
- ZINTERSTORE 目标集合 集合数量 集合1 集合2
# 向集合存入数据127.0.0.1:6379> ZADD name 1 zhansgan(integer) 1127.0.0.1:6379> ZADD name 2 wangwu(integer) 1127.0.0.1:6379> ZADD name1 1 zhangsan 2 zhaoliu(integer) 2127.0.0.1:6379> ZADD name 4 zhangsan(integer) 1# 查询name和name2的交集存入name3127.0.0.1:6379> ZINTERSTORE name3 2 name name1(integer) 1# 查看name3的元素127.0.0.1:6379> ZRANGE name3 0 -11) "zhangsan"
获取集合区间内的元素数量
- ZLEXCOUNT key min max
- [min最小值包含
- [max最大值包含
- (min最小值不包含
- (max最大值不包含
- -最小值,开头位置
- +最大值,结尾位置
# 向集合添加元素127.0.0.1:6379> ZADD name 1 a 2 b 3 c 4 d 5 e 6 f 7 d(integer) 6# 获取name集合a到f区间的元素数量127.0.0.1:6379> ZLEXCOUNT name [a [f(integer) 6
获取集合索引区间的元素
- ZRANGE key begin end 【WITHSCORES可选,用于显示分数】
# 显示集合所有值,不显示分数127.0.0.1:6379> ZRANGE name 0 -11) "a"2) "b"3) "c"4) "e"5) "f"6) "d"# 显示集合元素和分数127.0.0.1:6379> ZRANGE name 0 -1 WITHSCORES 1) "a" 2) "1" 3) "b" 4) "2" 5) "c" 6) "3" 7) "e" 8) "5" 9) "f"10) "6"11) "d"12) "7"
获取集合指定区间的元素
- ZRANGEBYLEX key min max
- [min最小值包含
- [max最大值包含
- (min最小值不包含
- (max最大值不包含
- -最小值,开头位置
- +最大值,结尾位置
# 添加数据127.0.0.1:6379> ZADD test 1 a 2 b 3 c 4 d(integer) 4# 获取test开头到元素c的所有元素,包含元素c127.0.0.1:6379> ZRANGEBYLEX test - [c1) "a"2) "b"3) "c"
获取指定分数区间的元素
- ZRANGEBYSCORE key min max 【WITHSCORES】【LIMIT offset count】
# 添加数据127.0.0.1:6379> ZADD test 1 a 2 b 3 c 4 d 5 e(integer) 5# 查询分数1到4的元素127.0.0.1:6379> ZRANGEBYSCORE test 1 41) "a"2) "b"3) "c"4) "d"# 带有分页的查询127.0.0.1:6379> ZRANGEBYSCORE test 1 4 withscores limit 0 11) "a"2) "1"
获取指定元素的索引
- ZRANK key member
# 获取c在test中的索引127.0.0.1:6379> ZRANK test c(integer) 2
移除有序集合多个元素
- ZREM key member1 member2…
# 删除test中的a,b127.0.0.1:6379> ZREM test a b(integer) 2
移除集合指定元素区间的元素
- ZREMRANGEBYLEX key min max,min、max可以使用通配符
# 删除开头到e的所有元素127.0.0.1:6379> ZREMRANGEBYLEX test - [e(integer) 3
移除集合指定索引内的元素
- ZREMRANGEBYRANK key start end【会根据分数排序之后删除】
# 添加元素127.0.0.1:6379> ZRANGE test 0 -11) "c"2) "b"3) "a"# 删除0到1的元素127.0.0.1:6379> ZREMRANGEBYRANK test 0 1(integer) 2# 查看,删除成功127.0.0.1:6379> ZRANGE test 0 -11) "a"
移除集合指定分数区间的元素
- ZREMRANGEBYSCORE key min max
# 添加数据127.0.0.1:6379> ZADD test 1 a 2 b 3 c 4 e(integer) 4# 移除数据127.0.0.1:6379> ZREMRANGEBYSCORE test 1 2(integer) 2# 移除成功127.0.0.1:6379> ZRANGE test 0 -11) "c"2) "e"
获取集合中的指定索引间的成员,根据分数从高到低排列
- ZREVRANGE key start end
# 添加数据127.0.0.1:6379> ZADD test 1 a 2 b 3 c 4 e(integer) 4# 根据分数从低到高127.0.0.1:6379> ZRANGE test 0 -11) "a"2) "b"3) "c"4) "e"# 根据分数从高到低127.0.0.1:6379> ZREVRANGE test 0 -11) "e"2) "c"3) "b"4) "a"
获取集合中的指定分数区间的成员,从高到低
- ZREVRANGEBYSCORE key max min
# 获取分数4到1的元素127.0.0.1:6379> ZREVRANGEBYSCORE test 4 11) "e"2) "c"3) "b"4) "a"
返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
- ZREVRANK key member
# 添加数据127.0.0.1:6379> ZADD test 1 a 2 b 3 c 4 e(integer) 4# 从高到低排列127.0.0.1:6379> ZREVRANGE test 0 -11) "e"2) "c"3) "b"4) "a"# 获取元素从高到低排列的索引127.0.0.1:6379> ZREVRANK test e(integer) 0
获取元素在集合中的分数
- ZSCOPE key member
# 元素e在集合test的分数127.0.0.1:6379> ZSCORE test e"4"
获取多个集合的并集存入新的集合
- ZUNIONSTORE 新集合 几个集合 集合1 集合2…
# 添加数据127.0.0.1:6379> ZADD test 1 a 2 b(integer) 2127.0.0.1:6379> ZADD test2 2 a 5 f(integer) 2# 将test和test2的并集存入test3,会将相同元素分数相加127.0.0.1:6379> ZUNIONSTORE test3 2 test test2(integer) 3127.0.0.1:6379> ZRANGE test3 0 -1 withscores1) "b"2) "2"3) "a"4) "3"5) "f"6) "5"
数据库命令
切换数据库
- redis默认16个数据库,0-15
- SELECT index
# 切换到1号数据库127.0.0.1:6379> SELECT 1OK# 切换成功127.0.0.1:6379[1]>
输出信息
- ECHO message
127.0.0.1:6379> ECHO 'hello word'"hello word"
退出命令行
- QUIT
127.0.0.1:6379> quit[root@iZbp1363mi9y3w91bv87luZ opt]#
清空数据库
清空当前数据库
- FLUSHDB
清空全部shujuku
- FLUSHDB
Jedis
导入依赖
- jedis是redis的java版本的客户端实现
<!-- Jedis Maven依赖 --><dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
HelloWord
修改redis配置文件
- redis默认开启了保护机制,我们需要修改配置文件。否则无法远程连接。如果是本地的话没有影响
# 用于指定哪些ip可以访问,远程访问我们需要注掉这个配置# bind 127.0.0.1# 是否开启保护模式,远程访问需要关闭这个。改为falseprotected-mode false# 配置连接密码requirepass zhangsong
- 编写代码,具体方法同redis命令
Jedis jedis = new Jedis("47.97.73.4", 6379);jedis.auth("zhangsong");jedis.set("name", "zhangsong");String name = jedis.get("name");
使用Jedis的连接池
public class test { private static JedisPool jedisPool; //初始化jedisPool static { //创建配置类 JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); //船舰jedisPool,传入地址和端口 jedisPool = new JedisPool(jedisPoolConfig, "47.97.73.4", 6379); } //测试 public static void main(String[] args) { Jedis jedis = jedisPool.getResource(); jedis.auth("zhangsong"); jedis.set("name", "zhangsong"); String name = jedis.get("name"); System.out.println(name); }}
配置文件
-
配置文件来源
-
可爱博主:AlanLee
-
博客地址:http://www.cnblogs.com/AlanLee
# Redis 配置文件
# 当配置中需要配置内存大小时,可以使用 1k, 5GB, 4M 等类似的格式,其转换方式如下(不区分大小写)
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# 内存配置大小写是一样的.比如 1gb 1Gb 1GB 1gB
# daemonize no 默认情况下,redis不是在后台运行的,如果需要在后台运行,把该项的值更改为yes
daemonize yes
# 当redis在后台运行的时候,Redis默认会把pid文件放在/var/run/redis.pid,你可以配置到其他地址。
# 当运行多个redis服务时,需要指定不同的pid文件和端口
pidfile /var/run/redis.pid
# 指定redis运行的端口,默认是6379
port 6379
# 指定redis只接收来自于该IP地址的请求,如果不进行设置,那么将处理所有请求,
# 在生产环境中最好设置该项
# bind 127.0.0.1
# Specify the path for the unix socket that will be used to listen for
# incoming connections. There is no default, so Redis will not listen
# on a unix socket when not specified.
#
# unixsocket /tmp/redis.sock
# unixsocketperm 755
# 设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接
# 0是关闭此设置
timeout 0
# 指定日志记录级别
# Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
# debug 记录很多信息,用于开发和测试
# varbose 有用的信息,不像debug会记录那么多
# notice 普通的verbose,常用于生产环境
# warning 只有非常重要或者严重的信息会记录到日志
loglevel debug
# 配置log文件地址
# 默认值为stdout,标准输出,若后台模式会输出到/dev/null
#logfile stdout
logfile /var/log/redis/redis.log
# To enable logging to the system logger, just set 'syslog-enabled' to yes,
# and optionally update the other syslog parameters to suit your needs.
# syslog-enabled no
# Specify the syslog identity.
# syslog-ident redis
# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
# syslog-facility local0
# 可用数据库数
# 默认值为16,默认数据库为0,数据库范围在0-(database-1)之间
databases 16
################################ 快照 #################################
#
# 保存数据到磁盘,格式如下:
#
# save <seconds> <changes>
#
# 指出在多长时间内,有多少次更新操作,就将数据同步到数据文件rdb。
# 相当于条件触发抓取快照,这个可以多个条件配合
#
# 比如默认配置文件中的设置,就设置了三个条件
#
# save 900 1 900秒内至少有1个key被改变
# save 300 10 300秒内至少有300个key被改变
# save 60 10000 60秒内至少有10000个key被改变
save 900 1
save 300 10
save 60 10000
# 存储至本地数据库时(持久化到rdb文件)是否压缩数据,默认为yes
rdbcompression yes
# 本地持久化数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
# 工作目录
#
# 数据库镜像备份的文件放置的路径。
# 这里的路径跟文件名要分开配置是因为redis在进行备份时,先会将当前数据库的状态写入到一个临时文件中,等备份完成时,
# 再把该该临时文件替换为上面所指定的文件,而这里的临时文件和上面所配置的备份文件都会放在这个指定的路径当中。
#
# AOF文件也会存放在这个目录下面
#
# 注意这里必须制定一个目录而不是文件
dir ./
################################# 复制 #################################
# 主从复制. 设置该数据库为其他数据库的从数据库.
# 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
#
# slaveof <masterip> <masterport>
# 当master服务设置了密码保护时(用requirepass制定的密码)
# slav服务连接master的密码
#
# masterauth <master-password>
# 当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:
#
# 1) 如果slave-serve-stale-data设置为yes(默认设置),从库会继续相应客户端的请求
#
# 2) 如果slave-serve-stale-data是指为no,出去INFO和SLAVOF命令之外的任何请求都会返回一个
# 错误"SYNC with master in progress"
#
slave-serve-stale-data yes
# 从库会按照一个时间间隔向主库发送PINGs.可以通过repl-ping-slave-period设置这个时间间隔,默认是10秒
#
# repl-ping-slave-period 10
# repl-timeout 设置主库批量数据传输时间或者ping回复时间间隔,默认值是60秒
# 一定要确保repl-timeout大于repl-ping-slave-period
# repl-timeout 60
################################## 安全 ###################################
# 设置客户端连接后进行任何其他指定前需要使用的密码。
# 警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行150K次的密码尝试,这意味着你需要指定非常非常强大的密码来防止暴力破解
#
# requirepass foobared
# 命令重命名.
#
# 在一个共享环境下可以重命名相对危险的命令。比如把CONFIG重名为一个不容易猜测的字符。
#
# 举例:
#
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#
# 如果想删除一个命令,直接把它重命名为一个空字符""即可,如下:
#
# rename-command CONFIG ""
################################### 约束 ####################################
# 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,
# 如果设置 maxclients 0,表示不作限制。
# 当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
#
# maxclients 128
# 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key
# Redis同时也会移除空的list对象
#
# 当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作
#
# 注意:Redis新的vm机制,会把Key存放内存,Value会存放在swap区
#
# maxmemory的设置比较适合于把redis当作于类似memcached的缓存来使用,而不适合当做一个真实的DB。
# 当把Redis当做一个真实的数据库使用的时候,内存使用将是一个很大的开销
# maxmemory <bytes>
# 当内存达到最大值的时候Redis会选择删除哪些数据?有五种方式可供选择
#
# volatile-lru -> 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used )
# allkeys-lru -> 利用LRU算法移除任何key
# volatile-random -> 移除设置过过期时间的随机key
# allkeys->random -> remove a random key, any key
# volatile-ttl -> 移除即将过期的key(minor TTL)
# noeviction -> 不移除任何可以,只是返回一个写错误
#
# 注意:对于上面的策略,如果没有合适的key可以移除,当写的时候Redis会返回一个错误
#
# 写命令包括: set setnx setex append
# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
# getset mset msetnx exec sort
#
# 默认是:
#
# maxmemory-policy volatile-lru
# LRU 和 minimal TTL 算法都不是精准的算法,但是相对精确的算法(为了节省内存),随意你可以选择样本大小进行检测。
# Redis默认的灰选择3个样本进行检测,你可以通过maxmemory-samples进行设置
#
# maxmemory-samples 3
############################## AOF ###############################
# 默认情况下,redis会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁,如果发生诸如拉闸限电、拔插头等状况,那么将造成比较大范围的数据丢失。
# 所以redis提供了另外一种更加高效的数据库备份及灾难恢复方式。
# 开启append only模式之后,redis会把所接收到的每一次写操作请求都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态。
# 但是这样会造成appendonly.aof文件过大,所以redis还支持了BGREWRITEAOF指令,对appendonly.aof 进行重新整理。
# 你可以同时开启asynchronous dumps 和 AOF
appendonly no
# AOF文件名称 (默认: "appendonly.aof")
# appendfilename appendonly.aof
# Redis支持三种同步AOF文件的策略:
#
# no: 不进行同步,系统去操作 . Faster.
# always: always表示每次有写操作都进行同步. Slow, Safest.
# everysec: 表示对写操作进行累积,每秒同步一次. Compromise.
#
# 默认是"everysec",按照速度和安全折中这是最好的。
# 如果想让Redis能更高效的运行,你也可以设置为"no",让操作系统决定什么时候去执行
# 或者相反想让数据更安全你也可以设置为"always"
#
# 如果不确定就用 "everysec".
# appendfsync always
appendfsync everysec
# appendfsync no
# AOF策略设置为always或者everysec时,后台处理进程(后台保存或者AOF日志重写)会执行大量的I/O操作
# 在某些Linux配置中会阻止过长的fsync()请求。注意现在没有任何修复,即使fsync在另外一个线程进行处理
#
# 为了减缓这个问题,可以设置下面这个参数no-appendfsync-on-rewrite
#
# This means that while another child is saving the durability of Redis is
# the same as "appendfsync none", that in pratical terms means that it is
# possible to lost up to 30 seconds of log in the worst scenario (with the
# default Linux settings).
#
# If you have latency problems turn this to "yes". Otherwise leave it as
# "no" that is the safest pick from the point of view of durability.
no-appendfsync-on-rewrite no
# Automatic rewrite of the append only file.
# AOF 自动重写
# 当AOF文件增长到一定大小的时候Redis能够调用 BGREWRITEAOF 对日志文件进行重写
#
# 它是这样工作的:Redis会记住上次进行些日志后文件的大小(如果从开机以来还没进行过重写,那日子大小在开机的时候确定)
#
# 基础大小会同现在的大小进行比较。如果现在的大小比基础大小大制定的百分比,重写功能将启动
# 同时需要指定一个最小大小用于AOF重写,这个用于阻止即使文件很小但是增长幅度很大也去重写AOF文件的情况
# 设置 percentage 为0就关闭这个特性
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
################################## SLOW LOG ###################################
# Redis Slow Log 记录超过特定执行时间的命令。执行时间不包括I/O计算比如连接客户端,返回结果等,只是命令执行时间
#
# 可以通过两个参数设置slow log:一个是告诉Redis执行超过多少时间被记录的参数slowlog-log-slower-than(微妙),
# 另一个是slow log 的长度。当一个新命令被记录的时候最早的命令将被从队列中移除
# 下面的时间以微妙微单位,因此1000000代表一分钟。
# 注意制定一个负数将关闭慢日志,而设置为0将强制每个命令都会记录
slowlog-log-slower-than 10000
# 对日志长度没有限制,只是要注意它会消耗内存
# 可以通过 SLOWLOG RESET 回收被慢日志消耗的内存
slowlog-max-len 1024
################################ VM ###############################
### WARNING! Virtual Memory is deprecated in Redis 2.4
### The use of Virtual Memory is strongly discouraged.
# Virtual Memory allows Redis to work with datasets bigger than the actual
# amount of RAM needed to hold the whole dataset in memory.
# In order to do so very used keys are taken in memory while the other keys
# are swapped into a swap file, similarly to what operating systems do
# with memory pages.
#
# To enable VM just set 'vm-enabled' to yes, and set the following three
# VM parameters accordingly to your needs.
vm-enabled no
# vm-enabled yes
# This is the path of the Redis swap file. As you can guess, swap files
# can't be shared by different Redis instances, so make sure to use a swap
# file for every redis process you are running. Redis will complain if the
# swap file is already in use.
#
# The best kind of storage for the Redis swap file (that's accessed at random)
# is a Solid State Disk (SSD).
#
# *** WARNING *** if you are using a shared hosting the default of putting
# the swap file under /tmp is not secure. Create a dir with access granted
# only to Redis user and configure Redis to create the swap file there.
vm-swap-file /tmp/redis.swap
# vm-max-memory configures the VM to use at max the specified amount of
# RAM. Everything that deos not fit will be swapped on disk *if* possible, that
# is, if there is still enough contiguous space in the swap file.
#
# With vm-max-memory 0 the system will swap everything it can. Not a good
# default, just specify the max amount of RAM you can in bytes, but it's
# better to leave some margin. For instance specify an amount of RAM
# that's more or less between 60 and 80% of your free RAM.
vm-max-memory 0
# Redis swap files is split into pages. An object can be saved using multiple
# contiguous pages, but pages can't be shared between different objects.
# So if your page is too big, small objects swapped out on disk will waste
# a lot of space. If you page is too small, there is less space in the swap
# file (assuming you configured the same number of total swap file pages).
#
# If you use a lot of small objects, use a page size of 64 or 32 bytes.
# If you use a lot of big objects, use a bigger page size.
# If unsure, use the default :)
vm-page-size 32
# Number of total memory pages in the swap file.
# Given that the page table (a bitmap of free/used pages) is taken in memory,
# every 8 pages on disk will consume 1 byte of RAM.
#
# The total swap size is vm-page-size * vm-pages
#
# With the default of 32-bytes memory pages and 134217728 pages Redis will
# use a 4 GB swap file, that will use 16 MB of RAM for the page table.
#
# It's better to use the smallest acceptable value for your application,
# but the default is large in order to work in most conditions.
vm-pages 134217728
# Max number of VM I/O threads running at the same time.
# This threads are used to read/write data from/to swap file, since they
# also encode and decode objects from disk to memory or the reverse, a bigger
# number of threads can help with big objects even if they can't help with
# I/O itself as the physical device may not be able to couple with many
# reads/writes operations at the same time.
#
# The special value of 0 turn off threaded I/O and enables the blocking
# Virtual Memory implementation.
vm-max-threads 4
############################### ADVANCED CONFIG ###############################
# 当hash中包含超过指定元素个数并且最大的元素没有超过临界时,
# hash将以一种特殊的编码方式(大大减少内存使用)来存储,这里可以设置这两个临界值
# Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,
# 这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,
# 当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
hash-max-zipmap-entries 512
hash-max-zipmap-value 64
# list数据类型多少节点以下会采用去指针的紧凑存储格式。
# list数据类型节点值大小小于多少字节会采用紧凑存储格式。
list-max-ziplist-entries 512
list-max-ziplist-value 64
# set数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。
set-max-intset-entries 512
# zsort数据类型多少节点以下会采用去指针的紧凑存储格式。
# zsort数据类型节点值大小小于多少字节会采用紧凑存储格式。
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
# Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用
#
# 当你的使用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。
#
# 如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存
activerehashing yes
################################## INCLUDES ###################################
# 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
# include /path/to/local.conf
# include /path/to/other.conf
内存配置单位说明
- 1k => 1000 bytes
- 1kb => 1024 bytes
- 1m => 1000000 bytes
- 1mb => 10241024 bytes
- 1g => 1000000000 bytes
- 1gb => 10241024*1024 bytes
daemonize no
- daemonize no 默认情况下,redis不是在后台运行的,如果需要在后台运行,把该项的值更改为yes
pidfile /var/run/redis.pid
- 当redis在后台运行的时候,Redis默认会把pid文件放在/var/run/redis.pid,你可以配置到其他地址
- 当运行多个redis服务时,需要指定不同的pid文件和端口。如:pidfile /var/run/redis.pid
port 6379
- 指定redis运行的端口,默认是6379
- port 6379
bind 127.0.0.1
- 指定redis只接收来自于该IP地址的请求,如果不进行设置,那么将处理所有请求,在生产环境中最好设置该项
timeout 0
- 设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么关闭该连接
- 0是关闭此设置
loglevel debug
- 指定日志记录级别
- Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
- debug 记录很多信息,用于开发和测试
- varbose 有用的信息,不像debug会记录那么多
- notice 普通的verbose,常用于生产环境
- warning 只有非常重要或者严重的信息会记录到日志
logfile /var/log/redis/redis.log
- 配置log文件地址
- 默认值为stdout,标准输出,若后台模式会输出到/dev/null,也就是丢弃这些日志
databases 16
- 可用数据库数
- 默认值为16,默认数据库为0,数据库范围在0-(database-1)之间
save 900 1
- 保存数据到磁盘,格式如下:
- save
- 指出在多长时间内,有多少次更新操作,就将数据同步到数据文件rdb。
- 指出在多长时间内,有多少次更新操作,就将数据同步到数据文件rdb。
- 比如默认配置文件中的设置,就设置了三个条件
- save 900 1 900秒内至少有1个key被改变
- save 300 10 300秒内至少有300个key被改变
- save 60 10000 60秒内至少有10000个key被改变
rdbcompression yes
- 存储至本地数据库时(持久化到rdb文件)是否压缩数据,默认为yes
dbfilename dump.rdb
- 本地持久化数据库文件名,默认值为dump.rdb
dir ./
- 工作目录,包含日志文件、持久化文件等
- 数据库镜像备份的文件放置的路径。
- 这里的路径跟文件名要分开配置是因为redis在进行备份时,先会将当前数据库的状态写入到一个临时文件中,等备份完成时,
- 再把该该临时文件替换为上面所指定的文件,而这里的临时文件和上面所配置的备份文件都会放在这个指定的路径当中。
- AOF文件也会存放在这个目录下面
- 注意这里必须制定一个目录而不是文件
slaveof <masterip> <masterport>
- 主从复制. 设置该数据库为其他数据库的从数据库
- 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
masterauth <master-password>
- 当master服务设置了密码保护时(用requirepass制定的密码)
- slav服务连接master的密码
slave-serve-stale-data yes
- 当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:
- 1) 如果slave-serve-stale-data设置为yes(默认设置),从库会继续相应客户端的请求
- 2) 如果slave-serve-stale-data是指为no,出去INFO和SLAVOF命令之外的任何请求都会返回一个错误"SYNC with master in progress"
repl-ping-slave-period 10
- 从库会按照一个时间间隔向主库发送PINGs.可以通过repl-ping-slave-period设置这个时间间隔,默认是10秒
repl-timeout 60
- repl-timeout 设置主库批量数据传输时间或者ping回复时间间隔,默认值是60秒
- 一定要确保repl-timeout大于repl-ping-slave-period
requirepass foobared
- 设置客户端连接后进行任何其他指定前需要使用的密码
- 警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行150K次的密码尝试,这意味着你需要指定非常非常强大的密码来防止暴力破解
rename-command CONFIG “”
- 命令重命名.
- 在一个共享环境下可以重命名相对危险的命令。比如把CONFIG重名为一个不容易猜测的字符。
- 举例:
- rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
- 如果想删除一个命令,直接把它重命名为一个空字符""即可,如下:rename-command CONFIG “”
maxclients 128
- 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,
- 如果设置 maxclients 0,表示不作限制。
- 当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
maxmemory <bytes>
- 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key。Redis同时也会移除空的list对象
- 当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作
- 注意:Redis新的vm机制,会把Key存放内存,Value会存放在swap区
- maxmemory的设置比较适合于把redis当作于类似memcached的缓存来使用,而不适合当做一个真实的DB。
- 当把Redis当做一个真实的数据库使用的时候,内存使用将是一个很大的开销
maxmemory-policy volatile-lru
- 当内存达到最大值的时候Redis会选择删除哪些数据?有五种方式可供选择
- volatile-lru -> 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used )
- allkeys-lru -> 利用LRU算法移除任何key
- volatile-random -> 移除设置过过期时间的随机key
- allkeys->random -> remove a random key, any key
- volatile-ttl -> 移除即将过期的key(minor TTL)
- noeviction -> 不移除任何可以,只是返回一个写错误
- 注意:对于上面的策略,如果没有合适的key可以移除,当写的时候Redis会返回一个错误
- 写命令包括: set setnx setex append
- incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
- sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
- zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
- getset mset msetnx exec sort默认是:maxmemory-policy volatile-lru
maxmemory-samples 3
- LRU 和 minimal TTL 算法都不是精准的算法,但是相对精确的算法(为了节省内存),随意你可以选择样本大小进行检测。
- Redis默认的灰选择3个样本进行检测,你可以通过maxmemory-samples进行设置
appendonly no
- 默认情况下,redis会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁,如果发生诸如拉闸限电、拔插头等状况那么将造成比较大范围的数据丢失。
- 所以redis提供了另外一种更加高效的数据库备份及灾难恢复方式。
- 开启append only模式之后,redis会把所接收到的每一次写操作请求都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态。
- 但是这样会造成appendonly.aof文件过大,所以redis还支持了BGREWRITEAOF指令,对appendonly.aof 进行重新整理。
- 你可以同时开启asynchronous dumps 和 AOF
appendfilename appendonly.aof
- AOF文件名称 (默认: “appendonly.aof”)
appendfsync everysec
- Redis支持三种同步AOF文件的策略:
- no: 不进行同步,系统去操作 。Faster
- always: always表示每次有写操作都进行同步。Slow, Safest
- everysec: 表示对写操作进行累积,每秒同步一次。Compromise
- 默认是"everysec",按照速度和安全折中这是最好的
- 如果想让Redis能更高效的运行,你也可以设置为"no",让操作系统决定什么时候去执行
- 或者相反想让数据更安全你也可以设置为"always"
- 如果不确定就用 “everysec”
no-appendfsync-on-rewrite no
- AOF策略设置为always或者everysec时,后台处理进程(后台保存或者AOF日志重写)会执行大量的I/O操作
- 在某些Linux配置中会阻止过长的fsync()请求。注意现在没有任何修复,即使fsync在另外一个线程进行处理
- 为了减缓这个问题,可以设置下面这个参数no-appendfsync-on-rewrite
auto-aof-rewrite-percentage 100和auto-aof-rewrite-min-size 64mb
- AOF 自动重写
- 当AOF文件增长到一定大小的时候Redis能够调用 BGREWRITEAOF 对日志文件进行重写
- 它是这样工作的:Redis会记住上次进行些日志后文件的大小(如果从开机以来还没进行过重写,那日子大小在开机的时候确定)
- 基础大小会同现在的大小进行比较。如果现在的大小比基础大小大制定的百分比,重写功能将启动
- 同时需要指定一个最小大小用于AOF重写,这个用于阻止即使文件很小但是增长幅度很大也去重写AOF文件的情况
- 设置 percentage 为0就关闭这个特性
slowlog-log-slower-than 10000
- Redis Slow Log 记录超过特定执行时间的命令。执行时间不包括I/O计算比如连接客户端,返回结果等,只是命令执行时间
- 可以通过两个参数设置slow log:一个是告诉Redis执行超过多少时间被记录的参数slowlog-log-slower-than(微秒),
- 另一个是slow log 的长度。当一个新命令被记录的时候最早的命令将被从队列中移除
- 下面的时间以微妙微单位,因此1000000代表一分钟。
- 注意制定一个负数将关闭慢日志,而设置为0将强制每个命令都会记录
- slowlog-log-slower-than 10000
slowlog-max-len 1024
- 对日志长度没有限制,只是要注意它会消耗内存
- 可以通过 SLOWLOG RESET 回收被慢日志消耗的内存
hash配置
- 当hash中包含超过指定元素个数并且最大的元素没有超过临界时,
- Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,
- 这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,
- 当成员数量增大时会自动转成真正的HashMap,此时encoding为ht
- hash将以一种特殊的编码方式(大大减少内存使用)来存储,这里可以设置这两个临界值
hash-max-zipmap-entries 512
- 键值对最大数目
hash-max-zipmap-value 64
- 值占用空间最大大小
list配置
list-max-ziplist-entries 512
- list数据类型多少节点以下会采用去指针的紧凑存储格式
list-max-ziplist-value 64
- list数据类型节点值大小小于多少字节会采用紧凑存储格式
set配置
set-max-intset-entries 512
- set数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。
zset配置
zset-max-ziplist-entries 128
- zsort数据类型多少节点以下会采用去指针的紧凑存储格式
zset-max-ziplist-value 64
- zsort数据类型节点值大小小于多少字节会采用紧凑存储格式
activerehashing yes
- Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用
- 当你的使用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。
- 如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存
include /path/to/local.conf
- 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
持久化
redis提供了不同计别的持久化方式
- RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.
- AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.
- 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.
- 你也可以同时开启两种持久化方式, 在这种情况下, 当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.
- 最重要的事情是了解RDB和AOF持久化方式的不同,让我们以RDB持久化方式开始:
RDB
RDB优点
-
RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集.
-
RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复.
-
RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
-
与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.
-
RDB默认使用bgsave(非阻塞操作)进行快照保存,除此还有save命令,这个命令是阻塞的
RDB缺点
- 如果你希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合你.虽然你可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),是Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,你可能会丢失几分钟的数据.
- RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度.
配置RDB
-
dbfilename dump.rdb
- 说明:设置本地数据库文件名,默认值为 dump.rdb
- 经验:通常设置为dump-端口号.rdb
-
dir
- 说明:设置存储.rdb文件的路径
- 经验:通常设置成存储空间较大的目录中,目录名称data
-
rdbcompression yes
-
说明:设置存储至本地数据库时是否压缩数据,默认为 yes,采用 LZF 压缩
-
经验:通常默认为开启状态,如果设置为no,可以节省 CPU 运行时间,但会使存储的文件变大(巨大)
-
-
rdbchecksum yes
- 说明:设置是否进行RDB文件格式校验,该校验过程在写文件和读文件过程均进行
- 经验:通常默认为开启状态,如果设置为no,可以节约读写性过程约10%时间消耗,但是存储一定的数据损坏风险
-
设置save
# 3600秒内发生一次写操作,就进行RDB操作
save 3600 1
# 禁用RDB
save ""
RDB文件
- RDB使用二进制存储文件
REDIS0009ú redis-ver^E6.2.5ú
redis-bitsÀ@ú^EctimeÂ-èbaú^Hused-mem¸O^M^@ú^Laof-preambleÀ^@þ^@û^A^@^@^Dname^Hzhangsanÿ'g/Æ"¬uO
RDB启动方式
- save阻塞操作生成快照
- bgsave非阻塞操作生成快照,会开启一个子线程用于同步数据
AOF
AOF优点
- 使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.
- AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.
- Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
- AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。
AOF缺点
- 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
- 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
AOF配置
# 开启AOF
appendonly yes
# AOF文件保存策略,always(每次)、everysec(每秒)、no(系统控制)
appendfsync evertsec
# AOF文件名称
appendfilename filename
# 工作路径
dir /
# AOF重写,将多个重复命令合并。重写命令bgrewriteaof
# 定义一个最小重写大小
auto-aof-rewrite-min-size size
# 超过定义的多少进行重写。自动重写触发条件(当前AOF文件大小-定义的基础大小)/ 基础文件大小 >= 定义基础文件大小
auto-aof-rewrite-percentage percentage
AOF文件
- 是以类似redis命令存储的,会将每一步操作都存储进去
*3
$3
set
$4
name
$8
zhangsan
同步缓冲区文件
-
write操作会触发延迟写(delayed write)机制,Linux在内核提供页缓冲区用
来提高硬盘IO性能。write操作在写入系统缓冲区后直接返回。同步硬盘操作依
赖于系统调度机制,列如:缓冲区页空间写满或达到特定时间周期。同步文件之
前,如果此时系统故障宕机,缓冲区内数据将丢失。
-
fsync针对单个文件操作(比如AOF文件),做强制硬盘同步,fsync将阻塞知道
写入硬盘完成后返回,保证了数据持久化。
事务
定义
- 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断
- 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行
事务命令
- MULTI【开启事务】
- EXEC【执行事务队列中的命令】
- DISCARD【取消事务】
# 开启事务
127.0.0.1:6379> MULTI
OK
# 注意现在执行命令,命令不会直接执行,而是会入队列,在输入exec命令之后执行
127.0.0.1:6379(TX)> set name zhangsan
QUEUED
# 执行队列中的命令
127.0.0.1:6379(TX)> EXEC
1) OK
# 添加成功
127.0.0.1:6379> KEYS *
1) "name"
# 开启事务
127.0.0.1:6379> MULTI
OK
# 添加命令
127.0.0.1:6379(TX)> set age 1
QUEUED
# 取消事务
127.0.0.1:6379(TX)> DISCARD
OK
# 没有添加
127.0.0.1:6379> KEYS *
1) "name"
锁
-
WATCh key1 key2…【未指定键添加锁,当事务需要用到的键发生改变时,指定事务会失败】
-
UNWATCH key1 key2…【取消锁】
# 为age添加锁
127.0.0.1:6379> WATCH age
OK
# 开启事务
127.0.0.1:6379> MULTI
OK
# 修改age
127.0.0.1:6379(TX)> INCR age
QUEUED
# 失败,因为我开启另外一个客户端修改了age,所以会失败
127.0.0.1:6379(TX)> EXEC
(nil)
删除策略
逐出算法
- 详细可以查看官网,http://www.redis.cn/commands/expire.html
影响逐出算法的配置
- maxmemory【最大内存大小,0表示不限制大小】
核心配置
- daemonize yes**|**no【设置服务器以守护进程的方式运行】
- bind 127.0.0.1【绑定主机地址】
- port 6379【设置服务器端口号】
- databases 16【设置数据库数量】
服务器基础配置
日志配置
- loglevel debug**|verbose|notice|**warning【设置服务器以指定日志记录级别】
- logfile 端口号.log【日志记录文件名】
- 注意:日志级别开发期设置为verbose即可,生产环境中配置为notice,简化日志输出量,降低写日志IO的频度
客户端配置
- maxclients 0 【设置同一时间最大客户端连接数,默认无限制。当客户端连接到达上限,Redis会关闭新的连接】
- timeout 300【客户端闲置等待最大时长,达到最大值后关闭连接。如需关闭该功能,设置为 0】
多服务器快捷配置
- include /path/server-端口号.conf【导入并加载指定配置文件信息,用于快速创建redis公共配置较多的redis实例配置文件,便于维护】
HyperLogLog
介绍
- 用于进行基数统计,不是集合,不保存数据,只记录数量而不是具体数据
- 核心是基数估算算法,最终数值存在一定误差
- 误差范围:基数估计的结果是一个带有 0.81% 标准错误的近似值
- 耗空间极小,每个hyperloglog key占用了12K的内存用于标记基数
- pfadd命令不是一次性分配12K内存使用,会随着基数的增加内存逐渐增大
- Pfmerge命令合并后占用的存储空间为12K,无论合并之前数据量多少
添加指定元素到 HyperLogLog 中
- PFADD key element1 element2…【向基数集添加数据】
# 向基数集添加数据
127.0.0.1:6379> PFADD age 1 1 2 2 3 3 4 4
(integer) 1
# 统计基数
127.0.0.1:6379> PFCOUNT age
(integer) 4
返回给定 HyperLogLog 的基数估算值
- PFCOUNT key
将多个 HyperLogLog 合并为一个 HyperLogLog
- PFMERGE 目标基数集名称 基数集1 基数集2…
# 将age和age2合并放到age3中
127.0.0.1:6379> PFMERGE age3 age age2
OK
# 统计基数
127.0.0.1:6379> PFCOUNT age3
(integer) 6