2017年12月

一、发布和订阅

除了任务队列以外,redis还有一种基于“发布/订阅”模式的消息传递,使得客户端可以订阅某个频道,当频道有消息产生时,会把消息传递到所有的订阅者。和列表不一样的是,发布和订阅可以是一对多的关系,即同一个消息可以同时传递到多个客户端(订阅者)。而列表只能允许一个客户端接收一个消息。

订阅和退订的命令是PUBLISH/SUBSCRIBEPUBLISH是向频道发送消息,SUBSCRIBE是订阅频道。

1.1 发布

往指定频道发布消息的操作:

PUBLISH channel message

消息发送成功后,将会返回一个整数,表示收到这条消息的订阅者数量,如果没有任何客户端订阅频道,返回0。

一个要注意的问题是消息发布后不会被持久化,如果当前没有订阅者订阅频道,后续再订阅也不会收到订阅前的消息。

- 阅读剩余部分 -

一、问题描述

windows下,time.Parse()的时区和time.Format()的时区是一致的。

但是在linux环境下,time.Parse()的默认时区是UTCtime.Format()的时区默认是本地,两者如果不处理好就会导致错误。

package main
import "time"
import "fmt"
func main(){
    t, err := time.Parse("2006-01-02 15:04:05", "2017-12-03 22:01:02")
    if err != nil{
        fmt.Println(err)
        return
    }
    fmt.Println(t)
    fmt.Println(time.Now())
    fmt.Println(time.Now().Sub(t).Seconds())
}

输出:

2017-12-03 22:01:02 +0000 UTC
2017-12-03 22:15:26.592204446 +0800 CST m=+0.003020091
-27935.407549533

很明显能看到两者的时区不同并且如果把两者时间相减结果也不符合预期。

二、解决方法

使用time.ParseInLocation()而不是time.Parse()

package main

import "time"
import "fmt"

func main(){
    localTime, err := time.ParseInLocation("2006-01-02 15:04:05", "2017-12-03 22:01:02", time.Local)
    if err != nil{
        fmt.Println(err)
        return
    }
    fmt.Println(localTime)
    fmt.Println(time.Now())
    fmt.Println(time.Now().Sub(localTime).Seconds())
}

结果:

2017-12-03 22:01:02 +0800 CST
2017-12-03 22:18:26.288174547 +0800 CST m=+0.001532618
1044.288357362

一、任务队列概述

消息队列,顾名思义就是一个用来传递任务的队列。消息队列在开发中十分常见,经常用在页面后台处理需要很长时间的操作时,例如发送邮件、短信以及进行复杂数据运算操作等,这些操作通常会阻塞页面相当长的时间,为了避免用户等待太久,一般会先给用户页面进行相应,然后在后台使用独立的线程或者进程来处理这些复杂的操作。

消息队列分为两个部分,生产者和消费者。生产者负责把任务放进队列,消费者则负责从队列中取出任务执行。最常见的一个场景是:当我们在某个站点注册账号时,一般都会给我们的邮箱发送邮件验证,由于发送邮件比较耗时,并且邮件的实时性要求也不是很高,所以这里就可以使用消息队列来完成。先把发送邮件放到队列中,然后开启另外的一个线程专门读取任务,读取邮件并发送出去。

- 阅读剩余部分 -

网站中经常需要用到网站限流,例如限制用户恶意爬虫获取网页信息以及在网站访问流量大时限制访问频率等等,这里使用redis做一个简单的网站登录限制案例。

一、使用EXPIRE进行访问频率限制

逻辑:用户登入网页,判断是否为第一次登入,如果是,创建一个新键记录访问次数为1,并设置超时时间。后面再登入时先判断键是否存在且大于访问次数限制,如果是的话,返回错误页面,否则访问次数+1,正常访问。

- 阅读剩余部分 -

一、安装

redis中操作redis的模块为redis-py,使用pip install redis或者easy_install redis安装即可,也可以进去https://pypi.python.org/pypi/redis下载源码安装。

二、使用

安装好模块后,使用import redis即可导入模块。

2.1 创建连接

r = redis.StrictRedis()  # 默认连接127.0.0.1:6379
r = redis.StrictRedis(host="127.0.0.1", port=6379, db=0)  #显示指定主机、端口号和数据库

- 阅读剩余部分 -

ColorTable00 0 4
ColorTable01 8388608 4
ColorTable02 32768 4
ColorTable03 8421376 4
ColorTable04 128 4
ColorTable05 8388736 4
ColorTable06 32896 4
ColorTable07 12632256 4
ColorTable08 8421504 4
ColorTable09 16711680 4
ColorTable10 65280 4
ColorTable11 16776960 4
ColorTable12 255 4
ColorTable13 16711935 4
ColorTable14 65535 4
ColorTable15 16777215 4
CtrlKeyShortcutsDisabled 0 4
CursorSize 25 4
EnableColorSelection 0 4
ExtendedEditKey 1 4
ExtendedEditKeyCustom 0 4
FaceName DefaultTTFont 1
FilterOnPaste 1 4
FontFamily 0 4
FontSize 1048576 4
FontWeight 0 4
ForceV2 1 4
FullScreen 0 4
HistoryBufferSize 50 4
HistoryNoDup 0 4
InsertMode 1 4
LineSelection 1 4
LineWrap 1 4
LoadConIme 1 4
NumberOfHistoryBuffers 4 4
PopupColors 245 4
QuickEdit 1 4
ScreenBufferSize 589889656 4
ScreenColors 7 4
ScrollScale 1 4
TrimLeadingZeros 0 4
WindowAlpha 255 4
WindowSize 1966200 4
WordDelimiters 0 4
[Error 259]


## 二、增加和删除键值

- `CreateKey(key, sub_key)`:创建一个新键,如果键存在就不会创建。
- `SetValueEx(key, value_name, reserved, type, value)`:给一个键值赋值,如果键不存在将会自动创建。
- `SetValue(key, sub_key, type, value)`:设置一个子键,并给予一个默认值`value`。
- `DeleteKey(key, sub_key)`:删除键

示例:

key = reg.OpenKey(reg.HKEY_CURRENT_USER, "Console")
try:

newKey = reg.CreateKey(key, r"test")  # 创建一个子键
reg.SetValueEx(newKey, r"newKey", 0, reg.REG_SZ, "HelloWorld") 
reg.SetValue(newKey, r"newSubKey", reg.REG_SZ, "Hey")

except Exception as e:

print e

运行后的结果:

![](https://i.maqian.xin/2017/12/20171203121447.png)

## 三、问题

### 3.1 WindwosError: Error 5

没有权限导致的,`OpenKey` 中的`sam` 变量表明了操作的权限,默认是`KEY_READ` ,改成`KEY_ALL_ACCESS` 然后以管理员身份运行即可。例如:

KEY = r"SYSTEMControlSet001ControlClass{4d36e968-e325-11ce-bfc1-08002be10318}"
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, KEY, 0, _winreg.KEY_ALL_ACCESS)

一、expire和ttl命令

1.1 基本用法

Redis中的EXPIER 命令可以给键值设置过期时间,相关的命令及其格式为:

EXPIRE key seconds
PEXPIRE key milliseconds

两个命令分别表示设置秒级和毫秒级别的过期时间,到期之后系统会自动删除该键。

EXPIRE 命令返回1 表示设置过期时间成功,返回0 表示键不存在或者设置失败。

127.0.0.1:6379> set k 1
OK
127.0.0.1:6379> expire k 60
(integer) 1
127.0.0.1:6379> expire x 1
(integer) 0

- 阅读剩余部分 -