go-common/app/job/main/click/service/redis.go

241 lines
6.1 KiB
Go
Raw Normal View History

2019-04-22 10:49:16 +00:00
package service
import (
"context"
"fmt"
"strconv"
"time"
"go-common/library/cache/redis"
"go-common/library/log"
farm "github.com/dgryski/go-farm"
)
const (
// aid_ip
_anonymousePlayedKey = "nm:%d"
// aid bvid
_anonymouseBvIDKey = "nb:%d"
// bvid's last played aid
_bvIDLastPlayedKey = "bv:%d"
// Mid last played key
_midHashKey = "mid:%d"
_buvidToDidKey = "%d:bdid"
// 改短成6分钟
_hkeyExpire = 600
)
func (s *Service) midKey(mid int64) (key string) {
key = fmt.Sprintf(_midHashKey, mid%s.c.HashNum)
return
}
func (s *Service) bvKey(bvID string) (key string) {
num := int64(farm.Hash32([]byte(bvID)))
key = fmt.Sprintf(_bvIDLastPlayedKey, num%s.c.HashNum)
return
}
func (s *Service) buvidToDidKey(buvid string, aid int64) (key string) {
num := int64(farm.Hash32([]byte(fmt.Sprintf("%s_%d", buvid, aid))))
key = fmt.Sprintf(_buvidToDidKey, num%s.c.HashNum)
return
}
func (s *Service) anonymouseKey(aid, epID int64, ip string) (key string) {
var str string
if epID == 0 {
str = strconv.Itoa(int(aid)) + ip
} else {
str = strconv.Itoa(int(aid)) + ip + strconv.Itoa(int(epID))
}
num := int64(farm.Hash32([]byte(str)))
key = fmt.Sprintf(_anonymousePlayedKey, num%s.c.HashNum)
return
}
func (s *Service) anonymouseBvIDKey(aid int64, bvid string) (key string) {
str := strconv.Itoa(int(aid)) + bvid
num := int64(farm.Hash32([]byte(str)))
key = fmt.Sprintf(_anonymouseBvIDKey, num%s.c.HashNum)
return
}
// canCount 同一个IP一分钟同一个bvid五分钟
func (s *Service) canCount(c context.Context, aid, epID int64, ip string, stime int64, bvid string) (can bool) {
var (
err error
lastPlayTime int64
bvLastPlayTime int64
hKey = s.anonymouseKey(aid, epID, ip)
hbvKey = s.anonymouseBvIDKey(aid, bvid)
conn = s.redis.Get(c)
pTime = stime + s.c.CacheConf.NewAnonymousCacheTime
now = time.Now().Unix()
ipCan bool
bvCan bool
)
var field = aid
if epID > 0 {
field = epID
}
defer conn.Close()
if lastPlayTime, err = redis.Int64(conn.Do("HGET", hKey, field)); err != nil {
if err == redis.ErrNil {
if _, err = conn.Do("HSET", hKey, field, pTime); err != nil {
log.Error("conn.Do(HSET, %s, %d, %d) error(%v)", hKey, field, pTime, err)
return
}
ipCan = true
} else {
log.Error("conn.Do(HGET, %s, %d) error(%v)", hKey, field, err)
return
}
}
if bvLastPlayTime, err = redis.Int64(conn.Do("HGET", hbvKey, field)); err != nil {
if err == redis.ErrNil {
if _, err = conn.Do("HSET", hbvKey, field, pTime); err != nil {
log.Error("conn.Do(HSET, %s, %d, %d)", hbvKey, field, pTime)
return
}
bvCan = true
} else {
log.Error("conn.Do(HGET, %s, %d) error(%v)", hbvKey, field, err)
return
}
}
if ipCan && bvCan {
can = true
return
}
if now > lastPlayTime && now > bvLastPlayTime {
if err = conn.Send("HSET", hKey, field, now+s.c.CacheConf.NewAnonymousCacheTime); err != nil {
log.Error("conn.Send(HSET, %s, %s, %d) error(%v)", hKey, field, now+s.c.CacheConf.NewAnonymousCacheTime, err)
return
}
if err = conn.Send("EXPIRE", hKey, _hkeyExpire); err != nil {
log.Error("conn.Do(EXPIRE, %s, %d) error(%v)", hKey, _hkeyExpire, err)
return
}
if err = conn.Send("HSET", hbvKey, field, now+s.c.CacheConf.NewAnonymousBvCacheTime); err != nil {
log.Error("conn.Send(HSET, %s, %d, %d) error(%v)", hbvKey, field, now+s.c.CacheConf.NewAnonymousBvCacheTime, err)
return
}
if err = conn.Send("EXPIRE", hbvKey, _hkeyExpire); err != nil {
log.Error("conn.Do(EXPIRE, %s, %d) error(%v)", hbvKey, _hkeyExpire, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)")
return
}
for i := 0; i < 4; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive error(%v)", err)
return
}
}
can = true
}
return
}
func (s *Service) isReplay(c context.Context, mid, aid int64, bvID string, gapTime int64) (is bool) {
var (
hKey string
field string
conn = s.redis.Get(c)
value int64
err error
now = time.Now().Unix()
)
defer conn.Close()
if mid > 0 {
hKey = s.midKey(mid)
field = strconv.Itoa(int(mid))
} else {
hKey = s.bvKey(bvID)
field = bvID
}
// aid << 32 | ptime
if value, err = redis.Int64(conn.Do("HGET", hKey, field)); err != nil {
if err != redis.ErrNil {
log.Error("conn.Do(HGET, %s, %s) error(%s)", hKey, field, err)
return
}
err = nil
}
if value != 0 {
rOid := value >> 32
rNow := value & 0xffffffff
if rOid == aid && now-rNow < gapTime {
is = true
return
}
}
value = aid<<32 | now
if err = conn.Send("HSET", hKey, field, value); err != nil {
log.Error("conn.Do(HSET, %s, %s, %s) error(%v)", hKey, field, value, err)
return
}
if err = conn.Send("EXPIRE", hKey, _hkeyExpire); err != nil {
log.Error("conn.Do(EXPIRE, %s, %d)", hKey, _hkeyExpire)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)")
return
}
for i := 0; i < 2; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive error(%v)", err)
return
}
}
return
}
func (s *Service) getRealDid(c context.Context, buvid string, aid int64) (did string, err error) {
var (
conn = s.redis.Get(c)
key = s.buvidToDidKey(buvid, aid)
)
defer conn.Close()
if did, err = redis.String(conn.Do("HGET", key, buvid)); err != nil {
if err != redis.ErrNil {
log.Error("redis.String(conn.Do(HGET, %s, %s)) error(%v)", key, buvid, err)
return
}
err = nil
}
return
}
func (s *Service) setRealDid(c context.Context, buvid string, aid int64, did string) (err error) {
var (
conn = s.redis.Get(c)
key = s.buvidToDidKey(buvid, aid)
)
defer conn.Close()
if err = conn.Send("HSET", key, buvid, did); err != nil {
log.Error("conn.Do(HSET, %s, %s, %s) error(%v)", key, buvid, did, err)
return
}
if err = conn.Send("EXPIRE", key, _hkeyExpire); err != nil {
log.Error("conn.Send(EXPIRE, %s, %d) error(%v)", key, _hkeyExpire, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
for i := 0; i < 2; i++ {
if _, err = conn.Receive(); err != nil {
log.Error("conn.Receive error(%v)", err)
return
}
}
return
}