go-common/app/job/main/click/service/redis.go
2019-04-22 18:49:16 +08:00

241 lines
6.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}