redis 实践1

参考文档 http://redisdoc.com/index.html
详情的redis 命令参考这个文档

  • [x] 总结下来 其实redis 是用来处理string的一个db 最基本的是string

1. 设置string 并且设置 过期时间 查看还剩时间

语法 :
SET key value [EX seconds] [PX milliseconds] [NX|XX]

> set name zhangsan EX 100 XX 
> get name 
> ttl name # 查看还有多少秒
> presist name # 取消掉name 上面的到计时

一旦倒计时结束之后将被删除
> get name
(nil)

> ttl name
(integer) -2 # -2 表示已经过期

127.0.0.1:6379> get age
"12"
127.0.0.1:6379> ttl age
(integer) -1 # 表示永久存在

2. 对string 进行修改

set name "新数据"
append name "new append data"

3. 可以在命令行直接执行redis 的一些命令

dingmac@ubuntu:~$ redis-cli config get dir
1) "dir"
2) "/var/lib/redis"

4. 在 parallel 里面添加ubuntu 并且实现本地redis 和 ubuntu 中redis的连接

怎么实现 master slave 配置

参考https://www.digitalocean.com/community/tutorials/how-to-configure-redis-replication-on-ubuntu-16-04

最主要的是在 redis.conf 文件中修改 bind 127.0.0.1 本地ip

To disable replication and promote the current server to master status, use the slaveof command with the value of no one:

slaveof no one # 取消slave 关系

防火墙也要修改 端口 ubuntu 使用 ufw 命令查看

centos 使用service iptables status

centos 安装redis https://www.tecmint.com/install-redis-server-in-centos-ubuntu-debian/

或者参考 https://linode.com/docs/databases/redis/install-and-configure-redis-on-centos-7/

其实可以在本地开启两个服务器

> redis-server --port 8888 # 端口8888
> redis-server # 默认端口
  1. 在redis 数据库之间migrate key
创建两个server
1. > redis-server --port 8888
2. > redis-server 
在6379 端口服务器 添加数据
lpush xingong zhangsan lisi wangwu zhaoliu
> migrate 127.0.0.1 8888 xingong 0 100
迁移到127.0.0.1 8888 端口 对应的0 db timeout 是100 

6. 一个redis 默认有16个database 通过select 命令选择

关于怎么存储数据到redis 数据库参考这个文章 > http://www.mikeperham.com/2015/09/24/storing-data-with-redis/

redis数据存储的三个问题

There are several questions to answer when determining how to use Redis for different datasets:

Can I flush the dataset without affecting other datasets?

我可以在不影响其他数据集的情况下清除这个数据集么?

Can I tune the persistence strategy per dataset? For transactional data, you want real-time persistence with AOF. For cache, you want infrequent(罕见) RDB snapshots or no persistence at all.

[我可以使用“调整持久战略” 在每个字符集么对于事务性的数据 我想实时的持续化到AOF 文件。对于cache 我想尽量少的持续化数据 或者压根不存到文件 ]

Can I scale Redis per dataset? Redis is single-threaded and can perform X ops/sec so consider that your performance “budget”. Datasets in the same Redis instance will share that budget. What happens when your traffic spikes and the cache data uses the entire budget? Now your job queue slows to a crawl.

我可以单独的控制单个数据集的规模么? redis是单线程 可以执行多少options/seconds 的阈值 这个我们可以认为是最大的请求数。可以通过redis-benchmark 命令查看

redis-benchmark --help # 查看帮助

在同一个instance 上面的数据集share 同一个阈值 当你的traffic 阻塞了或者cache 数据使用了整个budget (预售) 那么你在队列里面的命令就会低速爬行 性能糟糕

那么怎么解决

  1. 使用namespace 就是cache 的index 使用cache:name 这样的形式
    对于上面提到的三个问题 都是NO NO NO

  2. 使用多个数据库 就是默认的redis 包含16 个db 通过select 0-15 的方式切换 也可以到redis.conf 文件中修改多少个db

能解决第一个问题 但是第二 和第三都是NO
代码可以使用 redis://localhost:6379/0 方式调用特定 db 可以使用move 命令进行数据库之间的数据传输 ;
flushdb 会只清除本db 的数据 而不会影响到其他db

同一个redis server 上面的所有db 享受同一个budget 还有不能单独配置 哪个db 不持久化到disk

  1. instance 通过实例的方式进行区分,就是创建多个redis-server 可以是本机 也可以是不同server 上面的

对于上面的问题是 YES YES YES

如果是单纯的是对cache 进行处理 使用 memcached

I recommend memcached because it is designed for caching: it performs no disk I/O at all and is multithreaded so it can scale across all cores, handling 100,000s of requests per second. Redis is limited to a single core so it will hit a scalability limit before memcached. Using Redis for caching is totally reasonable if you want to stick with one tool and are comfortable with the necessary configuration and lower scalability limit per process. Redis does have a nice advantage that it can persist the cache, making it much faster to warm up upon restart.

move key direction_db

7. object 命令可以用来纠错

OBJECT 命令有多个子命令:

OBJECT REFCOUNT <key> 返回给定 key 引用所储存的值的次数。此命令主要用于除错。
OBJECT ENCODING <key> 返回给定 key 锁储存的值所使用的内部表示(representation)。
OBJECT IDLETIME <key> 返回给定 key 自储存以来的空闲时间(idle, 没有被读取也没有被写入),以秒为单位。


对象可以以多种方式编码:
字符串可以被编码为 raw (一般字符串)或 int (为了节约内存,Redis 会将字符串表示的 64 位有符号整数编码为整数来进行储存)。
列表可以被编码为 ziplist 或 linkedlist 。 ziplist 是为节约大小较小的列表空间而作的特殊表示。
集合可以被编码为 intset 或者 hashtable 。 intset 是只储存数字的小集合的特殊表示。
哈希表可以编码为 zipmap 或者 hashtable 。 zipmap 是小哈希表的特殊表示。
有序集合可以被编码为 ziplist 或者 skiplist 格式。 ziplist 用于表示小的有序集合,而 skiplist 则用于表示任何大小的有序集合。
127.0.0.1:6379> object encoding game
"embstr"
127.0.0.1:6379> object idletime game
(integer) 380
127.0.0.1:6379> object refcount game
(integer) 1

127.0.0.1:6379> get wow
"11111111111111111111111111111111111111111111111111111111111"
127.0.0.1:6379> object encoding wow
"raw
127.0.0.1:6379> set age 12
OK
127.0.0.1:6379> object encoding age
"int"

8. restore 恢复数据 在migrate 命令使用的时候也是用到了 restore 命令 只不过是隐式调用

127.0.0.1:6379> set greeting-again "hello world"
127.0.0.1:6379> dump greeting-again
"\x00\x0bhello world\b\x00\xb2\xd1\xa5\x06\x0f\xde*\x0c"
127.0.0.1:6379> restore greeting-again 0 "\x00\x0bhello world\b\x00\xb2\xd1\xa5\x06\x0f\xde*\x0c" replace
OK
带replace 字表示如果有key 叫greeting-again 就替换

9. 要排序还可以使用sort 命令

SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC | DESC] [ALPHA] [STORE destination]

# 返回或保存给定列表、集合、有序集合 key 中经过排序的元素

# 排序默认以数字作为对象,值被解释为双精度浮点数,然后进行比较。
  • 默认情况下 认以数字作为对象,值被解释为双精度浮点数,然后进行比较
  • 使用alpaha 修饰符 修饰符对字符串进行排序
127.0.0.1:6379> sort as alpha
1) "adashsad"
2) "as"
3) "asd"
4) "dasd3"
5) "djw"
6) "dsakjdhas"
7) "sdashdg"
  • 使用limit 限制返回的数据数 类似于 mysql 的 limit 但是 默认要写offset
127.0.0.1:6379> sort as alpha limit 3 3

是从3开始3个元素 offset0 开始

查看demo http://redisdoc.com/key/sort.html

  • 可以通过使用外部 key 进行排序

    • by 通过使用 BY 选项,可以让 uid 按其他键的元素来排序。
      比如说, 以下代码让 uid 键按照 user_level_{uid} 的大小来排序:

      sort uid by user_level_* get user_name_* desc
    • get 使用 GET 选项, 可以根据排序的结果来取出相应的键值。
      比如说, 以下代码先排序 uid , 再取出键 user_name_{uid} 的值:

      sort uid by user_level_* get user_name_* desc
      
    • 可以使用多个get

      127.0.0.1:6379> sort uid by user_level_* get user_name_* get user_level_*
    • GET 有一个额外的参数规则,那就是 —— 可以用 # 获取被排序键的值

      127.0.0.1:6379> sort uid by user_level_* get # get user_name_* get user_level_*

      获取外部键,但不进行排序 可以指定一个不存在的key 进行排序
    • SORT uid BY not-exists-key

      SORT uid BY not-exists-key GET # GET user_level_* GET user_name_*
    • 哈希表进行排序

      HMSET user_info_1 name jack level 10
      HMSET user_info_2 name peter level 25
      ...
      
      sort uid by user_info_*->level get user_info_*->name desc
      
      按照哈希值进行排序

    保存排序结果

    sort 只是简单地返回排序结果并不进行任何保存操作 可以使用store 选项进行存储

10. scan 迭代

语法:
SCAN cursor [MATCH pattern] [COUNT count]
  • SCAN 命令用于迭代当前数据库中的数据库键。
  • SSCAN 命令用于迭代集合键中的元素。
  • HSCAN 命令用于迭代哈希键中的键值对。
  • ZSCAN 命令用于迭代有序集合中的元素(包括元素成员和元素分值)

CAUTION!
- SSCAN 命令、 HSCAN 命令和 ZSCAN 命令的第一个参数总是一个数据库键。
- 而 SCAN 命令则不需要在第一个参数提供任何数据库键 ——
因为它迭代的是当前数据库中的所有数据库键。

参考 sort文档
把这个文章多读几遍

11. bitcount 和 setbit 的使用

参考 Fast, easy, realtime metrics using Redis bitmaps

参考 http://redisdoc.com/string/bitcount.html#bitmap

假设现在我们希望记录自己网站上的用户的上线频率,比如说,计算用户 A 上线了多少天,用户 B 上线了多少天,诸如此类,以此作为数据,从而决定让哪些用户参加 beta 测试等活动 —— 这个模式可以使用 SETBIT 和 BITCOUNT 来实现。

比如说,每当用户在某一天上线的时候,我们就使用 SETBIT ,以用户名作为 key ,将那天所代表的网站的上线日作为 offset 参数,并将这个 offset 上的为设置为 1 。

举个例子,如果今天是网站上线的第 100 天,而用户 peter 在今天阅览过网站,那么执行命令 SETBIT peter 100 1 ;如果明天 peter 也继续阅览网站,那么执行命令 SETBIT peter 101 1 ,以此类推。

12. BITOP 操作bit or/and/not/xor 对数据进行bit 操作


# bitop 指的是 bit operation
对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。

operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种:

BITOP AND destkey key [key ...] ,对一个或多个 key 求逻辑并,并将结果保存到 destkey 。
BITOP OR destkey key [key ...] ,对一个或多个 key 求逻辑或,并将结果保存到 destkey 。
BITOP XOR destkey key [key ...] ,对一个或多个 key 求逻辑异或,并将结果保存到 destkey 。
BITOP NOT destkey key ,对给定 key 求逻辑非,并将结果保存到 destkey 。

13. bitfield BITMAP

参考 https://segmentfault.com/a/1190000009841792

上面看不懂可以参考这篇文章 https://www.infoworld.com/article/3226768/nosql/manage-access-control-using-redis-bitfields.html

http://redisdoc.com/string/bitfield.html 文档地址

文档里面讲的不是太清楚举例

bitfield 是对bit进行操作的一个工具 个setbit getbit 类似

语法

BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]

先讲 GET type offsetSET type offset value 这两个是什么意思

首先我们创建 一个key 叫bitkey 如果已经存在del bitkey

bitfield bitkey set i4 0 5 

首先解释一下 i4是什么意思 指的是有符号的4个位置 还可以使用u 表示没有符号的4个位置

这句话的意思是有符号四位数从index 0 位置开始设置成5 【101】

127.0.0.1:6379> bitfield bitkey get u1 0 get u1 1 get u1 2 get u1 3 
1) (integer) 0
2) (integer) 1
3) (integer) 0
4) (integer) 1

那么就讲到了 get 参数 u1 指的是没有符号的数 0 表示从index 0 开始 从左边开始index 从0 开始
四位的最高是 0 第一位是 1

现在查看下面例子

127.0.0.1:6379> bitfield bitkey get u3 1
1) (integer) 5
127.0.0.1:6379> bitfield bitkey get u3 2
1) (integer) 2
127.0.0.1:6379> bitfield bitkey get u3 3
1) (integer) 4

我现在是拉取的一个长度为 3的无符号数 bitkey 存的数据是 0101
- get u3 1 表示从index 1 开始取3个无符号数 得到的就是 101 那么就是5
- get u3 2表示从index 2 开始取三个无符号数 那么从bitkey 拿到两个数是01 自己在末端添加一个0 就变成 010 所有就是2
- get u3 3 表示从 index 3 开始取三位无符号数 那么从bitkey 里面拿到一个数是1 自己再末端添加两个0 就变成了 100 就是4

现在再看一下下面例子

127.0.0.1:6379> bitfield bitkey get i3 3
1) (integer) -4
127.0.0.1:6379> bitfield bitkey get i3 2
1) (integer) 2
127.0.0.1:6379> bitfield bitkey get i3 1
1) (integer) -3

同样的方式 只不过这次我们存到了有符号数中
- get i3 3 表示从index 3 开始存入的一个有符号数 就是100 为有符号数 前面都是1 因为最高位是1 也就是说这个数是 11..11100 点表示多个1 【先减1 然后再取反 得到的就是 00..00100 (有符号数负数的运算)】所以就是-4
- get i3 1 拿到的数是010 那么就是2
- get i3 1 拿到的是101 那么就是 11..11101 那么就是 -3

注意点

使用 GET 子命令对超出字符串当前范围的二进制位进行访问(包括键不存在的情况), 超出部分的二进制位的值将被当做是 0 。

使用 SET 子命令或者 INCRBY 子命令对超出字符串当前范围的二进制位进行访问将导致字符串被扩大, 被扩大的部分会使用值为 0 的二进制位进行填充。 在对字符串进行扩展时, 命令会根据字符串目前已有的最远端二进制位, 计算出执行操作所需的最小长度。

查看下面例子

127.0.0.1:6379> bitfield bitkey set i4 0 80
1) (integer) 0
127.0.0.1:6379> bitfield bitkey get i4 0
1) (integer) 0
127.0.0.1:6379> bitfield bitkey get u4 0
1) (integer) 0

在bitkey 中存储的数据是0 为什么是0 ? 80 的二进制是01010000 后面4位给了bitkey 所以是0000 查看下面例子就可以知道

127.0.0.1:6379> bitfield bitkey set i4 0 83
1) (integer) 0
127.0.0.1:6379> bitfield bitkey get i4 0
1) (integer) 3

现在查看INCRBY type offset increment

127.0.0.1:6379> bitfield bitkey incrby u1 1 1
1) (integer) 1
127.0.0.1:6379> bitfield bitkey get i4 0
1) (integer) 7

查看上面例子 bitfield bitkey incrby u1 1 1 表示在bitkey 的第一位 增加一个无符号数1 原来 bitkey 是3 【0011】 现在变成了 【0111】 就是7

那么现在 在执行一遍 你以为bitkey 变成 1011 了么? NO !又变成 3了

127.0.0.1:6379> bitfield bitkey incrby u1 1 1
1) (integer) 0

127.0.0.1:6379> bitfield bitkey get i4 0
1) (integer) 3

为啥?
原来的7 [0111] 第一位增加了一个1 按道理说是10

再列一遍

使用 SET 子命令或者 INCRBY 子命令对超出字符串当前范围的二进制位进行访问将导致字符串被扩大, 被扩大的部分会使用值为 0 的二进制位进行填充。 在对字符串进行扩展时, 命令会根据字符串目前已有的最远端二进制位, 计算出执行操作所需的最小长度。

还有一个子命令, 它可以改变之后执行的 INCRBY 子命令在发生溢出情况时的行为:

OVERFLOW [WRAP|SAT|FAIL]
127.0.0.1:6379> bitfield bitkey  incrby i8 0 3  overflow sat # overflow sat 没有用
1) (integer) -117
127.0.0.1:6379> bitfield bitkey overflow sat incrby i8 0 3 
1) (integer) -114
127.0.0.1:6379> bitfield bitkey overflow sat incrby i8 0 -300 
1) (integer) -128 # works
# 记得一定要写成下面的的格式

# 对于有符号数 都是127 加1 变成 -128 再减一又变成127 对于无符号数会从0 到255
  • WRAP 默认行为无符号u8 到255 之后加1 就变成 0 ,0减一就变成 255 ;有符号数 i8 到127 之后加一就变成-128 ,-128 减1 就变成 127
  • SAT 表示设置的值有下限 上限 u8 上限 255 下线 0 , i8 上限127 下线-128
  • fail 超过直接报错
127.0.0.1:6379> bitfield bitkey overflow fail incrby i8 0 -100
1) (nil)
127.0.0.1:6379> bitfield bitkey overflow fail incrby i8 0 -2
1) (integer) -114

还可以使用下面命令

BITFIELD mystring SET i8 #0 100 i8 #1 200
就是指第一个8位有符号数 设置成100 第二个设置成200 
深入理解 INCRBY

文档 http://redisdoc.com/string/bitfield.html 那个提问的那是我 :)

抛出问题

Hi 我对incrby 语法有些困惑 incrby type offset increment 中的这个offset到底是指的是什么 ? 是u4 对应的offset 还是 被增加的那个键的 offset ?

127.0.0.1:6379> del bitkey #first delete bitkey
127.0.0.1:6379> bitfield bitkey set u4 0 15
1) (integer) 0
127.0.0.1:6379> bitfield bitkey get u4 0
1) (integer) 15
127.0.0.1:6379> bitfield bitkey incrby u4 0 1
1) (integer) 0
127.0.0.1:6379> bitfield bitkey get u4 0
1) (integer) 0

上面是例子我设置了bitkey 是无符号数 1111 就是15 现在我操作了 bitfield bitkey incrby u4 0 1 我理解的是就是会增加 1 那么现在bitkey 就变成了 0 (默认overflow wrap)

下面是我困惑的example

127.0.0.1:6379> bitfield bitkey set u4 0 15
1) (integer) 0
127.0.0.1:6379> bitfield bitkey incrby u4 2 1
1) (integer) 13
127.0.0.1:6379> bitfield bitkey get u4 0
1) (integer) 15
127.0.0.1:6379> bitfield bitkey incrby u4 2 1
1) (integer) 14
127.0.0.1:6379> bitfield bitkey get u4 0
1) (integer) 15
127.0.0.1:6379> bitfield bitkey incrby u4 2 1
1) (integer) 15
127.0.0.1:6379> bitfield bitkey get u4 0
1) (integer) 15
127.0.0.1:6379> bitfield bitkey incrby u4 2 1
1) (integer) 0
127.0.0.1:6379> bitfield bitkey get u4 0
1) (integer) 12

我执行了4次 bitfield bitkey incrby u4 2 1 bitkey 才有变化 底层是怎么实现的?

等待大神出没

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值