rpl optimize

log head use pool
remove defer mutex
This commit is contained in:
siddontang 2014-11-19 10:26:50 +08:00
parent 1ca74b404a
commit 8ec2730235
8 changed files with 94 additions and 59 deletions

View File

@ -167,18 +167,9 @@ See [Clients](https://github.com/siddontang/ledisdb/wiki/Clients) to find or con
+ `pcall` and `xpcall` are not supported in lua, you can see the readme in [golua](https://github.com/aarzilli/golua). + `pcall` and `xpcall` are not supported in lua, you can see the readme in [golua](https://github.com/aarzilli/golua).
## Thanks ## Requirement
Gmail: cenqichao@gmail.com
Gmail: chendahui007@gmail.com
Gmail: cppgohan@gmail.com
Gmail: tiaotiaoyly@gmail.com
Gmail: wyk4true@gmail.com
+ go version >= 1.3
## Feedback ## Feedback

View File

@ -111,7 +111,7 @@ path = ""
# If sync is true, the new log must be sent to some slaves, and then commit. # If sync is true, the new log must be sent to some slaves, and then commit.
# It will reduce performance but have better high availability. # It will reduce performance but have better high availability.
sync = true sync = false
# If sync is true, wait at last wait_sync_time milliseconds for slave syncing this log # If sync is true, wait at last wait_sync_time milliseconds for slave syncing this log
wait_sync_time = 500 wait_sync_time = 500

View File

@ -111,7 +111,7 @@ path = ""
# If sync is true, the new log must be sent to some slaves, and then commit. # If sync is true, the new log must be sent to some slaves, and then commit.
# It will reduce performance but have better high availability. # It will reduce performance but have better high availability.
sync = true sync = false
# If sync is true, wait at last wait_sync_time milliseconds for slave syncing this log # If sync is true, wait at last wait_sync_time milliseconds for slave syncing this log
wait_sync_time = 500 wait_sync_time = 500

View File

@ -100,12 +100,13 @@ type commitDataGetter interface {
func (l *Ledis) handleCommit(g commitDataGetter, c commiter) error { func (l *Ledis) handleCommit(g commitDataGetter, c commiter) error {
l.commitLock.Lock() l.commitLock.Lock()
defer l.commitLock.Unlock()
var err error var err error
if l.r != nil { if l.r != nil {
var rl *rpl.Log var rl *rpl.Log
if rl, err = l.r.Log(g.Data()); err != nil { if rl, err = l.r.Log(g.Data()); err != nil {
l.commitLock.Unlock()
log.Fatal("write wal error %s", err.Error()) log.Fatal("write wal error %s", err.Error())
return err return err
} }
@ -113,19 +114,25 @@ func (l *Ledis) handleCommit(g commitDataGetter, c commiter) error {
l.propagate(rl) l.propagate(rl)
if err = c.Commit(); err != nil { if err = c.Commit(); err != nil {
l.commitLock.Unlock()
log.Fatal("commit error %s", err.Error()) log.Fatal("commit error %s", err.Error())
l.noticeReplication() l.noticeReplication()
return err return err
} }
if err = l.r.UpdateCommitID(rl.ID); err != nil { if err = l.r.UpdateCommitID(rl.ID); err != nil {
l.commitLock.Unlock()
log.Fatal("update commit id error %s", err.Error()) log.Fatal("update commit id error %s", err.Error())
l.noticeReplication() l.noticeReplication()
return err return err
} }
return nil
} else { } else {
return c.Commit() err = c.Commit()
} }
l.commitLock.Unlock()
return err
} }

View File

@ -163,8 +163,12 @@ func (s *FileStore) LastID() (uint64, error) {
func (s *FileStore) StoreLog(l *Log) error { func (s *FileStore) StoreLog(l *Log) error {
s.wm.Lock() s.wm.Lock()
defer s.wm.Unlock() err := s.storeLog(l)
s.wm.Unlock()
return err
}
func (s *FileStore) storeLog(l *Log) error {
err := s.w.StoreLog(l) err := s.w.StoreLog(l)
if err == nil { if err == nil {
return nil return nil
@ -172,23 +176,24 @@ func (s *FileStore) StoreLog(l *Log) error {
return err return err
} }
s.rm.Lock()
var r *tableReader var r *tableReader
if r, err = s.w.Flush(); err != nil { r, err = s.w.Flush()
if err != nil {
log.Error("write table flush error %s, can not store now", err.Error()) log.Error("write table flush error %s, can not store now", err.Error())
s.w.Close() s.w.Close()
s.rm.Unlock()
return err return err
} }
s.rm.Lock()
s.rs = append(s.rs, r) s.rs = append(s.rs, r)
s.rm.Unlock() s.rm.Unlock()
return s.w.StoreLog(l) err = s.w.StoreLog(l)
return err
} }
func (s *FileStore) PurgeExpired(n int64) error { func (s *FileStore) PurgeExpired(n int64) error {

View File

@ -546,13 +546,18 @@ func (t *tableWriter) Flush() (*tableReader, error) {
} }
func (t *tableWriter) StoreLog(l *Log) error { func (t *tableWriter) StoreLog(l *Log) error {
t.Lock()
err := t.storeLog(l)
t.Unlock()
return err
}
func (t *tableWriter) storeLog(l *Log) error {
if l.ID == 0 { if l.ID == 0 {
return ErrStoreLogID return ErrStoreLogID
} }
t.Lock()
defer t.Unlock()
if t.closed { if t.closed {
return fmt.Errorf("table writer is closed") return fmt.Errorf("table writer is closed")
} }
@ -588,9 +593,11 @@ func (t *tableWriter) StoreLog(l *Log) error {
offsetPos := t.offsetPos offsetPos := t.offsetPos
if err := l.Encode(t.wb); err != nil { if err = l.Encode(t.wb); err != nil {
return err return err
} else if err = t.wb.Flush(); err != nil { }
if err = t.wb.Flush(); err != nil {
return err return err
} }
@ -652,12 +659,14 @@ func (t *tableWriter) GetLog(id uint64, l *Log) error {
func (t *tableWriter) Sync() error { func (t *tableWriter) Sync() error {
t.Lock() t.Lock()
defer t.Unlock()
var err error
if t.wf != nil { if t.wf != nil {
return t.wf.Sync() err = t.wf.Sync()
} }
return nil t.Unlock()
return err
} }
func (t *tableWriter) getLog(l *Log, pos int64) error { func (t *tableWriter) getLog(l *Log, pos int64) error {

View File

@ -4,8 +4,11 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"io" "io"
"sync"
) )
const LogHeadSize = 17
type Log struct { type Log struct {
ID uint64 ID uint64
CreateTime uint32 CreateTime uint32
@ -15,7 +18,7 @@ type Log struct {
} }
func (l *Log) HeadSize() int { func (l *Log) HeadSize() int {
return 17 return LogHeadSize
} }
func (l *Log) Size() int { func (l *Log) Size() int {
@ -23,7 +26,7 @@ func (l *Log) Size() int {
} }
func (l *Log) Marshal() ([]byte, error) { func (l *Log) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, l.HeadSize()+len(l.Data))) buf := bytes.NewBuffer(make([]byte, l.Size()))
buf.Reset() buf.Reset()
if err := l.Encode(buf); err != nil { if err := l.Encode(buf); err != nil {
@ -39,25 +42,32 @@ func (l *Log) Unmarshal(b []byte) error {
return l.Decode(buf) return l.Decode(buf)
} }
var headPool = sync.Pool{
New: func() interface{} { return make([]byte, LogHeadSize) },
}
func (l *Log) Encode(w io.Writer) error { func (l *Log) Encode(w io.Writer) error {
if err := binary.Write(w, binary.BigEndian, l.ID); err != nil { b := headPool.Get().([]byte)
pos := 0
binary.BigEndian.PutUint64(b[pos:], l.ID)
pos += 8
binary.BigEndian.PutUint32(b[pos:], uint32(l.CreateTime))
pos += 4
b[pos] = l.Compression
pos++
binary.BigEndian.PutUint32(b[pos:], uint32(len(l.Data)))
n, err := w.Write(b)
headPool.Put(b)
if err != nil {
return err return err
} else if n != LogHeadSize {
return io.ErrShortWrite
} }
if err := binary.Write(w, binary.BigEndian, l.CreateTime); err != nil { if n, err = w.Write(l.Data); err != nil {
return err
}
if _, err := w.Write([]byte{l.Compression}); err != nil {
return err
}
dataLen := uint32(len(l.Data))
if err := binary.Write(w, binary.BigEndian, dataLen); err != nil {
return err
}
if n, err := w.Write(l.Data); err != nil {
return err return err
} else if n != len(l.Data) { } else if n != len(l.Data) {
return io.ErrShortWrite return io.ErrShortWrite
@ -86,9 +96,10 @@ func (l *Log) Decode(r io.Reader) error {
} }
func (l *Log) DecodeHead(r io.Reader) (uint32, error) { func (l *Log) DecodeHead(r io.Reader) (uint32, error) {
buf := make([]byte, l.HeadSize()) buf := headPool.Get().([]byte)
if _, err := io.ReadFull(r, buf); err != nil { if _, err := io.ReadFull(r, buf); err != nil {
headPool.Put(buf)
return 0, err return 0, err
} }
@ -104,5 +115,7 @@ func (l *Log) DecodeHead(r io.Reader) (uint32, error) {
length := binary.BigEndian.Uint32(buf[pos:]) length := binary.BigEndian.Uint32(buf[pos:])
headPool.Put(buf)
return length, nil return length, nil
} }

View File

@ -114,10 +114,10 @@ func (r *Replication) Log(data []byte) (*Log, error) {
} }
r.m.Lock() r.m.Lock()
defer r.m.Unlock()
lastID, err := r.s.LastID() lastID, err := r.s.LastID()
if err != nil { if err != nil {
r.m.Unlock()
return nil, err return nil, err
} }
@ -125,6 +125,7 @@ func (r *Replication) Log(data []byte) (*Log, error) {
if lastID < commitId { if lastID < commitId {
lastID = commitId lastID = commitId
} else if lastID > commitId { } else if lastID > commitId {
r.m.Unlock()
return nil, ErrCommitIDBehind return nil, ErrCommitIDBehind
} }
@ -141,9 +142,12 @@ func (r *Replication) Log(data []byte) (*Log, error) {
l.Data = data l.Data = data
if err = r.s.StoreLog(l); err != nil { if err = r.s.StoreLog(l); err != nil {
r.m.Unlock()
return nil, err return nil, err
} }
r.m.Unlock()
r.ncm.Lock() r.ncm.Lock()
close(r.nc) close(r.nc)
r.nc = make(chan struct{}) r.nc = make(chan struct{})
@ -161,22 +165,24 @@ func (r *Replication) WaitLog() <-chan struct{} {
func (r *Replication) StoreLog(log *Log) error { func (r *Replication) StoreLog(log *Log) error {
r.m.Lock() r.m.Lock()
defer r.m.Unlock() err := r.s.StoreLog(log)
r.m.Unlock()
return r.s.StoreLog(log) return err
} }
func (r *Replication) FirstLogID() (uint64, error) { func (r *Replication) FirstLogID() (uint64, error) {
r.m.Lock() r.m.Lock()
defer r.m.Unlock()
id, err := r.s.FirstID() id, err := r.s.FirstID()
r.m.Unlock()
return id, err return id, err
} }
func (r *Replication) LastLogID() (uint64, error) { func (r *Replication) LastLogID() (uint64, error) {
r.m.Lock() r.m.Lock()
defer r.m.Unlock()
id, err := r.s.LastID() id, err := r.s.LastID()
r.m.Unlock()
return id, err return id, err
} }
@ -189,9 +195,10 @@ func (r *Replication) LastCommitID() (uint64, error) {
func (r *Replication) UpdateCommitID(id uint64) error { func (r *Replication) UpdateCommitID(id uint64) error {
r.m.Lock() r.m.Lock()
defer r.m.Unlock() err := r.updateCommitID(id, r.cfg.Replication.SyncLog == 2)
r.m.Unlock()
return r.updateCommitID(id, r.cfg.Replication.SyncLog == 2) return err
} }
func (r *Replication) Stat() (*Stat, error) { func (r *Replication) Stat() (*Stat, error) {
@ -231,14 +238,17 @@ func (r *Replication) updateCommitID(id uint64, force bool) error {
func (r *Replication) CommitIDBehind() (bool, error) { func (r *Replication) CommitIDBehind() (bool, error) {
r.m.Lock() r.m.Lock()
defer r.m.Unlock()
id, err := r.s.LastID() id, err := r.s.LastID()
if err != nil { if err != nil {
r.m.Unlock()
return false, err return false, err
} }
return id > r.commitID, nil behind := id > r.commitID
r.m.Unlock()
return behind, nil
} }
func (r *Replication) GetLog(id uint64, log *Log) error { func (r *Replication) GetLog(id uint64, log *Log) error {